Software Engineering·July 21, 2026·4 min read

Load Balancing

What a load balancer does, how traffic gets distributed, and what you need to know as a builder using managed platforms.

load-balancingscalingnetworkinginfrastructure

A load balancer sits in front of multiple servers and spreads incoming traffic across them. It's what lets you run more than one copy of your app behind a single address — the foundation of both handling more traffic and surviving a server failure. If Cartara flagged this in your diff, you likely changed something related to how your app handles multiple instances, session state, or health checks.

Why you need one

A single server has two problems: it can only handle so much traffic, and if it dies, your app goes down. Running multiple servers solves both — but now something has to decide which server handles each request and stop sending traffic to any server that fails. That's the load balancer.

It delivers two things at once:

  • Scalability — add more servers behind the balancer to handle more load
  • Availability — if one server goes down, the balancer routes around it automatically

This only works because your app servers need to be stateless: any server can handle any request, because session data lives in shared storage (a database or Redis) rather than on one specific machine.

Layer 4 vs Layer 7

Load balancers operate at one of two levels:

  • Layer 4 (transport) — routes by IP address and port, without looking at request content. Very fast, but can't make decisions based on URLs or headers
  • Layer 7 (application) — understands HTTP. Can route /api/* to one pool of servers and /images/* to another, terminate TLS, and inspect headers

Most web apps use Layer 7 because content-aware routing is so useful.

How the balancer picks a server

  • Round robin — hands requests to servers in rotation. Works well when servers are equal and requests are similar in cost
  • Weighted round robin — gives more powerful servers a larger share
  • Least connections — sends the next request to whichever server is handling the fewest active requests. Better when request duration varies a lot
  • IP hash — routes based on the client's IP, so a given user consistently hits the same server

Round robin and least connections cover most cases. Least connections is the safer default when request cost is uneven.

Health checks

A load balancer must know which servers are actually healthy — otherwise it'll keep sending traffic into a broken instance. It does this by periodically pinging each server (usually a /health endpoint) and removing any that fail from the rotation, adding them back when they recover.

Give your app a lightweight health endpoint that genuinely reflects whether it can serve requests — not just "the process is running" but "can I reach the database."

Sticky sessions: when and why to avoid them

Sometimes you want a given user to keep hitting the same server — for example if that server holds some in-memory session state. Sticky sessions (session affinity) do this.

The honest advice: prefer to avoid needing them. Sticky sessions undermine the stateless model — they make load distribution uneven and mean a server failure logs out affected users. The better approach is to keep session state in a shared store (Redis, a database) so any server can serve any user. Reach for sticky sessions only when you genuinely can't make the app stateless.

How this fits into the broader request path

A typical request path looks like:

CDN (edge cache) → Load balancer / API gateway → App servers → Database
  • Reverse proxy — a server that receives client requests and forwards them to backends (Nginx, HAProxy). A load balancer is essentially a reverse proxy that distributes across many backends; the terms overlap heavily
  • API gateway — adds API-specific concerns: authentication, rate limiting, request shaping. Common in multi-service setups
  • CDN — serves cached content close to users before traffic ever reaches your load balancer

What You'll See in Your Code

Cartara often flags stateful patterns that break horizontal scaling. A common example is storing session data in memory:

// Problematic: session lives in server memory
// Works fine with one server, breaks with multiple
const sessions = {}

app.post('/login', (req, res) => {
  const sessionId = generateId()
  sessions[sessionId] = { userId: req.body.userId }  // stored in memory
  res.cookie('sessionId', sessionId)
  res.json({ ok: true })
})

// Better: session stored in Redis (shared across all servers)
import { redis } from './redis'

app.post('/login', async (req, res) => {
  const sessionId = generateId()
  await redis.set(`session:${sessionId}`, JSON.stringify({ userId: req.body.userId }), 'EX', 86400)
  res.cookie('sessionId', sessionId)
  res.json({ ok: true })
})

A health check endpoint the load balancer can call:

app.get('/health', async (req, res) => {
  try {
    await db.$queryRaw`SELECT 1`  // verify DB connectivity
    res.json({ status: 'ok' })
  } catch (err) {
    res.status(503).json({ status: 'unhealthy', error: err.message })
  }
})

For builders on managed platforms

If you're on Vercel, Railway, Render, or similar — you already have load balancing without thinking about it. These platforms run multiple instances of your app behind a single URL automatically. What's worth doing deliberately:

  • Keep your app stateless so instances can scale horizontally
  • Expose a real health-check endpoint
  • Store sessions in a shared store, not in server memory

The infrastructure is handled; the architectural discipline is on you.

Related concepts

Managed Platforms
The platforms that abstract away cloud complexity — hosting, databases, auth, and AI infrastructure — and how to choose between them for your stage and stack.
Choosing a Tech Stack
How to pick tools for your app — the modern founder stack, decisions in detail, and what to avoid early.
Serverless Compute
What serverless means, when to use it, and the trade-offs that trip up builders — cold starts, statelessness, costs at scale.

Turn shipping into understanding

Cartara measures what your team actually learns from every AI coding session.

Join the waitlist