BizTechLab

IDEASINNOVATIONIMPACT

System Design Concepts

Why No Single Database Works

Why using one relational database for everything breaks down as an app grows — and how polyglot persistence fixes it.

2 August 20267 min read

Overview

For a long time, the default answer to "where do we store this?" was: one relational database. User accounts, orders, session tokens, search data, uploaded files — all of it went into the same MySQL or PostgreSQL instance. That works fine for a small app. It stops working once an app has real traffic, because a single database engine is built to be good at one kind of job, not every kind of job at once. The fix isn't picking a "better" database — it's accepting that different parts of your data need different storage engines, and using more than one on purpose. That approach has a name: polyglot persistence.

Why It Exists

A relational database is optimized for strong consistency and complex relationships between records — that's exactly what you want for orders, payments, and user accounts. But that same design makes it a poor fit for other jobs. Reading and writing millions of times per second for session data is expensive on a disk-backed relational engine, but trivial for an in-memory store like Redis. Fuzzy, ranked full-text search is something relational databases can bolt on, but a dedicated search engine like Elasticsearch does it far better out of the box. Storing millions of user-uploaded images cheaply and durably is not what a relational database is built for at all — that's what object storage like AWS S3 is for. None of these are flaws in the relational model. They're just trade-offs, and no single storage engine can sit on the good side of every trade-off simultaneously.

Real World Example

Take one ordinary action: a user logs into a shopping app, searches for a product, and uploads a profile photo. Under the hood, that one flow touches four different storage systems. Their account and password hash live in PostgreSQL, because that data needs strong consistency and relationships to orders and addresses. Their login session is checked on every single request, so it lives in Redis, which can answer in under a millisecond. Their product search hits Elasticsearch, which can rank results by relevance in a way a plain SQL `LIKE` query never will. Their uploaded photo goes straight to S3, because storing binary files in a relational database is slow and expensive at scale. No single database was "upgraded" to do all four jobs — four specialized tools were combined instead.

How It Works

Polyglot persistence isn't about installing five databases and hoping it works out. It's a deliberate architecture decision made per piece of data: look at how that data will actually be accessed — how often, how fast, how complex the queries need to be, whether it needs to survive a crash instantly or can tolerate a short delay — and pick the storage engine built for that access pattern. The application layer becomes the coordinator: it decides which service talks to which store, and it's usually the only thing that has a full picture of where everything lives. Each storage engine stays independent and is only ever accessed through the service that owns it — nothing else reaches in directly. That ownership boundary is what keeps a multi-database system manageable instead of turning into chaos.

Diagram

One user action, four storage engines, each doing the one thing it's good at

User logs in

needs consistency & relationships

Session is checked

needs sub-millisecond reads

User searches

needs ranked full-text search

User uploads a photo

needs cheap, durable storage

each routed to the engine built for it

PostgreSQL

Redis

Elasticsearch

AWS S3

all coordinated by

The Application Layer

the only thing that knows all four exist

Common Mistakes

Forcing every workload into the one database the team already knows

Why: It feels simpler short-term, but it produces an overloaded schema, slow queries competing for the same disk I/O, and a system that gets harder to scale the more it grows.

Fix: Pick the storage engine based on the actual access pattern of that specific data — not on which database is already running.

Adopting five different databases before there's a real bottleneck

Why: Every extra storage engine is something your team now has to operate, monitor, back up, and secure in production — that cost is real even when the engine itself is free.

Fix: Start with the fewest stores that work. Add a specialized one only when you can point to the specific problem it solves.

No clear ownership of which service can write to which store

Why: When multiple services write to the same database directly, nobody can reason about what's actually happening to the data, and consistency bugs become nearly impossible to trace.

Fix: Give each store a single owning service. Everything else goes through that service's API, never straight to its database.

Interview Questions

beginner

What is polyglot persistence?

Using more than one type of database in the same application, on purpose — picking each storage engine based on what that specific piece of data needs, instead of putting everything into one database.

intermediate

Why can't a single relational database handle both real-time caching and full-text search efficiently?

A relational database is disk-backed and optimized for consistency and complex queries across related tables — that's fundamentally slower than an in-memory store for the millions of tiny reads a cache needs, and it lacks the ranking/relevance algorithms (like BM25) that a dedicated search engine is built around. Both are technically possible in a relational database; neither is what it's optimized for.

senior

When decomposing a monolith's single database into multiple specialized stores, how do you decide the boundaries?

Group data by access pattern and by which service actually owns it, not by which tables happen to reference each other today. Each resulting store should have exactly one service that writes to it. Where two stores need to stay in sync (e.g. a cache and its source of truth), that's a signal you'll need a mechanism like Change Data Capture rather than dual writes from application code.

Production Best Practices

Do

Choose a storage engine based on the access pattern — latency, query complexity, write volume — not on familiarity alone.

Give each store a single owning service, and access it only through that service.

Start with the fewest stores that work, and add a specialized one only when a real bottleneck justifies it.

Don't

Don't force full-text search, real-time caching, and transactional data into one relational database just to avoid "more moving parts."

Don't adopt a new storage technology without someone on the team who can actually operate it in production.

Don't leave cross-store consistency to chance — plan for it explicitly, it becomes a production incident otherwise.

Comparison

Relational DBIn-Memory StoreSearch EngineObject Storage
Best atConsistency, relationshipsSub-millisecond readsRanked full-text searchCheap, durable large files
Query complexityHigh (joins, transactions)Low (key-value)Medium (relevance ranking)None (key-based lookup)
Typical latency~1–10 ms< 1 ms~10–50 ms~10–30 ms
Weak pointWrite throughput at scaleNo complex queriesNot a system of recordNo transactions

Related Articles