SE

Scaling strategies

Must-know concept1.3 hIntermediate

Horizontal vs vertical, stateless design, connection pooling.

"Vertical or horizontal" is shorthand for a deeper choice: do I throw a bigger machine at the problem, or change the design to share it across many small ones? The deeper choice shapes every other piece of your architecture.

The big idea

Two axes:

AttributeVertical (scale up)Horizontal (scale out)
ActionBigger box: more CPU, RAM, diskMore boxes; identical instances behind a load balancer
Code changeNoneStateless services; shared session store
LimitThe biggest box existsAlmost none for stateless tiers
CostCheap until it isn'tLinear-ish in compute
Failure modelOne machine = all your trafficLose one, the others keep running

For nearly every modern app: vertical for the database, horizontal for everything else.

Make services stateless

A stateless service stores no per-user state in memory between requests. Every request can be routed to any instance. That's the magic that makes horizontal scaling work.

Do

Store session data in a shared cache (Redis), database, or signed cookie.

const session = await redis.get(`session:${sid}`);
if (!session) return res.status(401).end();
Don't

Keep user objects in a module-level Map on each instance.

const sessions: Map<string, Session> = new Map();   // dies with the process
sessions.set(sid, session);

Connection pooling

Each app instance opens DB connections; if 50 instances each open 100 connections, that's 5,000 connections — far more than Postgres can handle. Pool inside each instance, and use a connection pooler (PgBouncer, RDS Proxy) in front of the database.

50× app podspool=10 each
PgBouncermultiplexes 500→50
Postgresmax_connections=100

Scaling the database

Stateful tiers are harder. The escalation:

  1. Vertical first

    Bigger instance. Postgres on a 64-core box goes a long way.

  2. Read replicas

    Reads go to replicas; writes still hit the primary. Watch for replication lag bugs.

  3. Sharding / partitioning

    Split data across multiple primaries by some key (user_id, tenant_id). Now you have a distributed system; the rules change.

  4. Specialised stores

    Move hot workloads off: ElasticSearch for search, Redis for sessions, Kafka for streams, ClickHouse for analytics.

Async over sync where you can

Synchronous work limits throughput to the latency of the slowest dependency. Pushing slow work to a queue/worker frees the request path:

APIreturns 202
Queue
Worker pool
Persist + notify

Order placed → return immediately, send the receipt email asynchronously. The user sees "order confirmed" in milliseconds; the email is queued for a worker.

Watch for hidden bottlenecks

Even a stateless horizontal service still funnels through:

The database
Eventually you hit max connections or write throughput.
Caches
Hot keys serialise on a single Redis instance.
Locks
Anywhere SELECT ... FOR UPDATE happens, contention kills throughput.
Third-party APIs
Their rate limit is your scaling ceiling.

In practice

Most teams scale prematurely. The right order:

  1. Profile the slow path.
  2. Add an index, cache the obvious answer, batch the N+1 queries.
  3. Add app instances (cheap, easy).
  4. Then consider read replicas, queues, sharding.

By the time you're sharding the database, you should know the system intimately. If you don't, sharding will make things worse.

Key takeaways

  • Vertical for the DB, horizontal for everything else.
  • Stateless services are a precondition for horizontal scale.
  • Connection pooling — both in-app and in front of the DB — keeps Postgres alive.
  • Push slow work to queues + workers; return fast.
  • Profile, index, cache before you shard. Most scaling work is engineering, not infra.

Checkpoint questions

Use these to test whether the lesson is clear enough to explain without rereading.

  1. 1Which parts of a system are easiest to scale horizontally, and which are hardest?
  2. 2Why does stateless service design make load balancing simpler?
  3. 3What hidden bottlenecks can remain after adding more application servers?
  4. 4When should you scale the database vertically before adding replicas or shards?

References

External resources for going deeper after the lesson above.