How would you store millions of likes?
Model a social like as a durable relationship, then scale the write path with partitioning, asynchronous work, and cached counters.
Explore the architectureThe core record
(post_id, user_id)
one unique like edge
A durable edge is the source of truth. Counts and feeds are derived views that can be rebuilt or updated asynchronously.
Architecture flow
Write once, build useful views
Separate the durable like edge from read-optimized counters. The stream connects them and lets each consumer scale independently.
Like API
Authenticate the actor and validate the post and requested action.
Idempotent write
Represent a like as a unique (postId, userId) edge. Retries should not create duplicate likes.
Durable event stream
Persist the change before acknowledging it; consumers can retry work from this log.
Sharded edge store
Partition each post into user-hash buckets to spread hot-post writes. Keep a user activity index for reverse lookups.
Async counters + cache
Aggregate increments in the background and serve a fast, eventually consistent count from a cache.
Change the inputs
Rate and shard simulator
See how evenly distributing writes changes the average load per shard. This back-of-the-envelope model assumes even routing and a planning target of 5,000 writes per second per shard.
Estimated even-share load
1,563writes / shard / sec
Planning target: 5,000 writes per shard per second (illustrative, not a vendor benchmark)
Suggested shards
10
at planning target
Likes per day
4,320,000,000
if rate is steady
Raw data per day
276.5 GB
at 64 bytes / edge
Storage estimate excludes indexes, replication, backups, compression, and stream retention. Capacity planning needs measured benchmarks and headroom.
Data model trade-offs
Store edges; derive counts
- Source of truth: a uniquely constrained like edge supports duplicate-safe retries and unlike operations.
- Hot posts: split post likes into buckets keyed by a stable hash of user ID; query fan-out becomes a deliberate read trade-off.
- Fast counts: aggregate stream events into counter buckets and cache their sum; the displayed count may lag briefly.
- Reverse access: maintain a user-oriented index or projection for “posts I liked” rather than scanning every post partition.
Diagram source
Mermaid flowchart
Copy this source into a Mermaid-compatible renderer to edit or share the architecture.
flowchart LR
U[App / user] --> A[Like API]
A --> V[Auth + validation]
V --> D[Idempotent write]
D --> E[Durable event stream]
E --> W[Like workers]
W --> S[(Sharded like-edge store)]
E --> C[Counter aggregators]
C --> K[(Counter cache)]
S --> R[Read API]
K --> R
R --> U
W --> I[(User activity index)]