Fundamentals
Growing a marketplace
A worked plan for a small marketplace that expects 10 times its traffic in a year, step by step with real numbers, and why it needs no sharding.
A small marketplace runs one app server and one Postgres instance. Peak traffic is 200 requests per second. Each request makes 3 queries that average 2 ms. The team expects 10 times the growth within a year. This page works through the plan with the numbers.
The big idea
Start with the numbers, then match each part of the system to the step it needs. Most of the growth can be handled by changes that are small and easy to undo. Sharding is not needed at this size, and the plan should say so.
Walking through it
First, the load in a year:
Today: 200 req/s × 3 queries = 600 queries/s on Postgres, which is trivial
In 1y: 2,000 req/s × 3 = 6,000 queries/s, about 90% of them reads
reads: 5,400/s writes: 600/sThen the plan, one step at a time:
- App tier. Assume each instance safely handles about 300 requests per second at 60% utilization, which is roughly 500 at full load. Then 2,000 ÷ 300 ≈ 7 instances. Make the servers stateless now, with sessions in Redis and uploads in S3. After that, scaling the app tier is a configuration change.
- Reads. 5,400 reads per second is within one Postgres's reach. But product pages are hot and repeated. A cache with a 90% hit rate cuts database reads to 5,400 × 0.1 = 540 per second. That buys years of headroom for a few hundred dollars a month.
- Writes. 600 writes per second is about 6% of a single primary's comfortable limit. Do not shard. Add one replica for failover and for analytics queries.
- Images. Move them to object storage behind a CDN now. They make up most of the bytes served, so this removes the largest share of the load.
The result handles 10 times the growth with no sharding, no microservices and no new data stores. Each step is a small change that can be reversed.
Common mistakes
- Sharding on the first day of growth. A 6% write load does not need it.
- Skipping the written plan. Without numbers, the next decision gets made during an outage.
- Forgetting that images are often the largest share of bytes. Move them early.
Check yourself
-
Why is 5,400 reads per second not a reason to shard?
Answer: one Postgres can serve those reads, and a cache with a 90% hit rate cuts database reads to about 540 per second.
-
Why move images to object storage first?
Answer: they are most of the bytes served, so moving them removes the largest share of the load.
Key takeaways
- Start from the numbers: requests per second, queries per request and the read-to-write ratio.
- Make the app tier stateless before you need to add instances.
- A cache can remove most of the read load for little cost.
- Shard only when write load or data size demands it. At 6% of one primary's limit, it does not.
Further learning
The scaling overview lists the rest of the path. For the step after this plan, see sharding.
Related
Scaling fundamentals
Vertical versus horizontal scaling, stateless services, the usual order in which a growing system adds parts, and how to find the real bottleneck. Start here for the scaling map.
The canonical scaling path
The usual sequence in which a successful web app adds parts, from one server to queues, shards and regions, with the symptom that triggers each step.
Caching
Where to put a cache, how to read and write through it, how to size it from hit-rate math, and how to keep it from serving stale data or melting down.
Sharding and partitioning
Split data across machines by choosing a shard key, hashing or ranging it, routing requests, handling hot spots, resharding without downtime and generating IDs that stay unique.
Stateless services
A stateless service can handle any request on any instance. Learn where the state goes instead, and the login bug that appears when a service keeps sessions in memory.