Skip to content
All articles
BackendArchitecturePostgreSQL

Lessons from Scaling a SaaS Backend

· 1 min read

Scaling a backend is rarely about one heroic rewrite. It’s a series of small, deliberate decisions that compound. Here are a few that made the biggest difference for me.

Measure before you optimize

It’s tempting to guess at bottlenecks. Don’t. Add tracing, look at real p95 numbers, and let the slow queries reveal themselves. Nine times out of ten the culprit is an N+1 query or a missing index — not the thing you assumed.

Cache the boring stuff

A read-through cache on hot, rarely-changing data removed the majority of our database load. The trick is invalidation: keep the cached shape small and tie it to a clear key so you can reason about staleness.

-- A missing index turned a 900ms query into a 12ms one.
CREATE INDEX CONCURRENTLY idx_events_tenant_created
  ON events (tenant_id, created_at DESC);

Make failure boring

  • Idempotent writes so retries are safe.
  • Backpressure so a spike degrades gracefully instead of falling over.
  • Dead-letter queues so a single poison message doesn’t stall a pipeline.

Keep the schema honest

As the product grew, the schema drifted. Regular migrations, foreign keys, and check constraints kept data integrity from quietly eroding — which saved countless debugging hours down the line.

None of this is glamorous, but reliability rarely is. It’s the accumulation of good defaults that lets a system grow without drama.


Back to all articles