Skip to content

Expert · Deployment and scaling · topic 50 of 54 · 30 min

Scaling: handling more users

Explanation

Scaling means handling more users without slowing down. You can buy a bigger server (vertical) or add more servers behind a load balancer (horizontal). Horizontal scaling needs stateless servers, health checks and a plan for the database: read replicas for heavy reading, and a CDN to serve images and files from near the user.

Two ways to grow

Vertical scaling means a bigger machine: more CPU, more RAM. It is simple, because the code does not change, but there is a top limit and one machine is still one point of failure. Horizontal scaling means more machines running the same app, with traffic shared between them. It can grow much further and survives one machine dying, but it needs some design work.

Think of it like this: Think of a toll plaza on a highway during Diwali traffic. Vertical scaling is making one booth faster with a quicker cashier. That helps, but only so much. Horizontal scaling is opening ten booths side by side, with a traffic marshal (the load balancer) waving each car to a free booth. If one booth closes, cars simply go to the others.
Vertical (bigger server)Horizontal (more servers)
HowUpgrade CPU and RAMAdd copies behind a load balancer
Code changesNoneServers must be stateless
LimitThe biggest machine you can rentVery high
If one machine failsThe app is downOthers keep serving

Stateless servers

A server is stateless when it keeps nothing important in its own memory between requests. If user sessions or uploaded files live in one server's memory or disk, the next request may go to a different server that knows nothing about them. So move state out: sessions to Redis, files to object storage (like Amazon S3), data to the database. Then any server can answer any request.

javascript
import { createClient } from 'redis';
const redis = createClient({ url: process.env.REDIS_URL });
await redis.connect();

async function saveSession(sessionId, data) {
  // expires after 24 hours
  await redis.set('session:' + sessionId, JSON.stringify(data), { EX: 60 * 60 * 24 });
}

async function loadSession(sessionId) {
  const raw = await redis.get('session:' + sessionId);
  return raw ? JSON.parse(raw) : null;
}
Runs on a server with Node.js. Every app server reads the same sessions from Redis.

Load balancers and health checks

A load balancer sits in front of your servers and passes each request to one of them. Round robin sends requests to each server in turn: A, B, C, A, B, C. Least connections sends each request to the server that is busy with the fewest requests right now, which is better when some requests are slow. Examples are nginx, HAProxy and the managed load balancers of every cloud.

output
upstream notes_api {
  least_conn;
  server 10.0.0.11:3000;
  server 10.0.0.12:3000;
  server 10.0.0.13:3000;
}
server {
  listen 80;
  location / { proxy_pass http://notes_api; }
}
An nginx config sharing traffic between three app servers with least connections.

A health check is a small endpoint, like GET /healthz, that the load balancer calls every few seconds. If a server stops answering 200, the load balancer stops sending it traffic until it recovers. Keep the check cheap, but make it test what matters, for example that the database answers SELECT 1.

Scaling the database

Most apps read far more than they write: people view products many times for each order. A read replica is a copy of the database that receives every change from the main (primary) database and answers read queries. Writes go to the primary; reads can go to replicas. The copy is not instant: the small delay is called replication lag.

Careful: Because of replication lag, a user who just saved something and then reads from a replica might not see their own change yet. For reads right after a write by the same user (like "show my new order"), read from the primary.

Sharding splits one big table across several databases, for example users with ids 1 to 1 crore in shard 1 and the next crore in shard 2. Each shard holds part of the data, so writes spread out too. It is powerful but complex: queries across shards and moving data between them are hard. Most apps never need it; try indexes, caching and replicas first.

CDNs and autoscaling

A CDN (Content Delivery Network) keeps copies of static files, like images, CSS, JavaScript and videos, on servers in many cities. A user in Guwahati gets the image from a nearby CDN server instead of your server in Mumbai: faster for them, less load for you. Autoscaling adds servers automatically when CPU or request count goes up, and removes them when traffic falls, so you pay for busy hours only.

Tip: Measure before you scale. Often one missing database index or one slow query is the real problem, and fixing it is cheaper than ten more servers.

Watch the lesson

Scaling: handling more users · 1/6

Vertical: bigger Horizontal: more

Scaling means serving more users without slowing down. There are two ways: a bigger server, or more servers.

Prefer a video by a teacher? Find free videos on “horizontal vs vertical scaling load balancer explained” on YouTube ↗

In real life: Board exam results day

On results day, a state board website gets lakhs of students in the first ten minutes, compared with a few hundred on a normal day. A well-prepared team runs the results API on many stateless servers behind a load balancer with health checks, and autoscaling adds more as traffic rises. Results are read-only, so they are served from read replicas and cached in Redis by roll number. The logo, CSS and PDF mark sheets come from a CDN. The primary database barely notices, and students get their results in seconds instead of a spinning wheel.

Practice (0/3 done)

Task 1 · Code · Javascript

Write leastConnections(servers) where servers is a list of { name, active, healthy }. Return the name of the healthy server with the fewest active connections. If two are tied, return the first one in the list. If no server is healthy, return null.

Task 2 · Code · Javascript

Write createRoundRobin(servers) that returns an object with a next() method. servers is a list of { name, healthy }. Each call to next() returns the name of the next server in turn (A, B, C, A, ...), skipping servers whose healthy is false at that moment. Health can change between calls. If no server is healthy, next() returns null.

Task 3 · Practice

A college results site normally has 200 visitors an hour, but on results day expects 2 lakh visitors in the first hour. Write a one-page scaling plan.

Quick quiz

Question 1

1.Which is horizontal scaling?

Question 2

2.Why must servers be stateless to scale horizontally?

Question 3

3.Some requests take 5 seconds and others 50 ms. Which load balancing method fits best?

Question 4

4.A user saves their profile and the page reloads showing the old name. Reads come from a replica. What is the likely cause?

Question 5

5.What does a CDN do?

Read more (free)

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

← Previous: Deploying to the cloud