Polyglot Persistence: Why Top Companies Use 4-5 Databases

Riassunto

PostgreSQL for transactions, MongoDB for the catalog, Redis for sessions, Neo4j for relationships: polyglot persistence picks each database by how its data is read. Learn how to sync them with CDC, choose consistency per domain, what Netflix, Uber and LinkedIn teach us, and a proportionate path for small businesses.

Alessandro Fiori Avatar

PhD · Politecnico di Torino

TL;DR. PostgreSQL for transactions, MongoDB for the catalog, Redis for sessions, Neo4j for relationships, Elasticsearch for search: that’s not a mess, it’s architecture. It’s called polyglot persistence — choosing each database for the way its data is read and written. This article covers when one database stops being enough, how to keep several databases in sync without corrupting data, how to pick consistency per domain, and what Netflix, Uber and LinkedIn teach us.

“Let’s just put everything in PostgreSQL — it works fine for now.” I’ve heard it in dozens of project meetings, and it’s usually the right call to get started. The trouble is “for now”. It hides a crisis that shows up right on schedule as the system grows: a 500-million-row products table with JSONB blobs whose query plans degrade; text search via LIKE '%keyword%' scanning the whole table with no relevance ranking; social-graph queries built on recursive self-joins that get slower with every hop; session lookups with a SELECT on every request exhausting the connection pool.

None of these is a PostgreSQL flaw. They’re symptoms of the same root mistake: forcing data with different shapes and usage patterns into one paradigm. The deck I use in my Advanced Data Modeling course at Politecnico di Torino puts it bluntly: forcing all data into a single paradigm is optimizing for developer convenience, not system performance.

This piece wraps up the technical part of our Digital Stack 2026 series. Over the past weeks we looked at the building blocks one by one — Neo4j, Kafka, InfluxDB, Airflow. Now we look at the whole picture.

The right tool for each job

Every data store was designed around a specific access pattern. Ignoring that design has a cost, and you usually pay it when change is hardest. This table is where every architecture conversation I have with students and clients begins:

Wrong choice vs right choice for five data patterns: documents, search, key-value, graph and time series
Wrong choice vs right choice: every access pattern has a natural home
Data patternWrong choiceRight choice
Flexible, nested documentsRelational, wide tables full of NULLsMongoDB
Keyword search with rankingSQL LIKEElasticsearch
Key lookups in microsecondsDisk-based databaseRedis
Graph traversalsRecursive SQL CTEsNeo4j
Time-series writes at millions/secRow-oriented databaseInfluxDB / TimescaleDB
ACID transactions, referential integrityEventually consistent NoSQLPostgreSQL / MySQL

The working definition is simple: polyglot persistence means choosing, within the same application, the storage technology that best fits each specific data access pattern. It’s not about brand loyalty or hype — it’s about how the data is queried.

“Isn’t PostgreSQL + JSONB enough?”

Students ask every year, and it’s a fair question. PostgreSQL’s JSONB support is excellent: GIN indexes, dedicated operators, partial document queries. For many projects it’s genuinely enough. It stops being enough when documents reach hundreds or thousands of fields with unpredictable schema evolution, when you need horizontal sharding across nodes (possible but complex in PostgreSQL), when write throughput exceeds what one primary can absorb, or when you need real relevance ranking rather than keyword presence. Rule of thumb: JSONB for occasional flexible fields on structured data; MongoDB when your primary access pattern is document-oriented. For a deeper dive on modeling document databases well, see our two-part guide to MongoDB design patterns.

Data gravity: where data lives matters

One concept explains why database decisions are so hard to reverse: data gravity. Applications and services accumulate around data the way planets gather around mass. Moving large datasets costs bandwidth, time and consistency risk. Latency grows with physical distance, from the same rack to the same availability zone to another region. And there are regulatory constraints: GDPR, for instance, may require certain data to stay in the EU.

The practical consequence is a rule worth its weight in gold: decide which store is the source of truth for each data domain before you build, not after you have petabytes to migrate. And treat each database as owning a bounded domain — services shouldn’t query another domain’s database directly, but go through APIs or events.

The real problem: keeping databases in sync

Picking five databases is the easy part. Keeping them consistent is the hard part. When a product changes in PostgreSQL, its Elasticsearch document must reflect it; when a user follows someone, the Neo4j graph needs to know.

The anti-pattern: dual writes

The naive approach writes to both databases from the same function:

# ANTI-PATTERN: dual write
def create_product(data):
    postgres_db.insert("products", data)        # step 1
    elasticsearch.index("products", data)       # step 2: what if this fails?

If step 1 succeeds and step 2 fails, the two stores silently diverge. There’s no atomicity across two external systems, and retry logic tends to create duplicates. As one of my slides puts it: dual writes without a coordinator lead to eventual corruption, not eventual consistency.

The standard fix: Change Data Capture

Change Data Capture (CDC) flips the approach. The application writes to one database only — the source of truth. A separate process reads that database’s transaction log and propagates every change to the other systems. Three benefits: full decoupling (the app knows nothing about other stores), guaranteed ordering (the log reflects actual commit order) and replay (a new consumer can rebuild its state from scratch). Debezium + Kafka is the production default: Debezium reads the PostgreSQL, MySQL or MongoDB log and publishes each change to a Kafka topic, and sink connectors deliver it downstream. We covered the details in Kafka Part 2.

Event sourcing, CQRS and Sagas

Three more patterns round out the toolbox — use them with judgment:

  • Event sourcing: instead of storing current state, store every change as an immutable event. State is rebuilt by replaying events, and every database becomes a projection you can rebuild anytime. You get a complete audit trail in return.
  • CQRS (Command Query Responsibility Segregation): separate the write model from the read model. Worth it when the read/write ratio is extremely lopsided (think 1000:1) and the two models need different schemas. It adds significant complexity — don’t adopt it unless scale truly demands it.
  • Saga: the answer to distributed transactions. Instead of a two-phase commit (2PC) across systems, split the transaction into local steps, each with a compensating transaction that undoes it if a later step fails.

Consistency: a per-domain decision

The CAP theorem says that in a distributed system facing network partitions, you choose between consistency and availability. In practice it’s not binary: there’s a spectrum from linearizability (everyone sees the same data at the same instant) to eventual consistency (everyone sees it sooner or later). Many databases let you tune it per operation: MongoDB via writeConcern and readPreference, Cassandra via levels like ONE or QUORUM.

Database consulting

Is your database slowing down or struggling to keep up with growth? We start from the data model and find the right solution, relational or NoSQL.

Discover database consulting →

The right question for each domain is: can users tolerate stale data? For how long? What are the consequences? Netflix is the textbook example. For the “Continue Watching” row it chose eventual consistency: if it lags a few seconds, business impact is near zero and the latency savings are huge. For billing and payments it uses MySQL with synchronous replication: strong consistency where it matters. The lesson: consistency isn’t a fixed property of the database, it’s a knob you set per data type based on impact.

Lambda, Kappa and Data Mesh

When data gets big and arrives continuously, you need higher-level architectural patterns. We compared Lambda and Kappa in the Kafka article: Lambda pairs a batch layer (the ground truth) with a speed layer (real time) at the cost of two pipelines; Kappa drops batch and recomputes history by replaying the log, with one codebase.

Data Mesh, proposed by Zhamak Dehghani in 2019, is different: it’s an organizational model, not a technology. It rests on four principles:

  1. Domain-oriented, decentralized ownership: each domain team (sales, logistics, marketing) owns and runs its data.
  2. Data as a product: with SLAs, versioned schemas and documentation, like any internal product.
  3. Self-serve platform: the central team provides infrastructure, not pipelines.
  4. Federated governance: global standards (schema registry, data contracts) with local autonomy.
Data WarehouseData LakeData Mesh
OwnershipCentral ITCentral ITDomain teams
SchemaRigid (star)Schema-on-readData contracts
Quality ownershipIT pipelineNobody, reallyDomain owners
Typical riskBI bottleneckData swampGovernance complexity

A warning I always give: many Data Mesh initiatives fail because they’re run as technology projects. They require organizational change first. For a small business with one tech team, Data Mesh is almost always the wrong scale.

Three real cases: Netflix, Uber and LinkedIn

Big-tech architectures shouldn’t be copied, but they’re worth studying: they show which problems emerge at extreme scale and which solutions held up over time. What follows is drawn from the three companies’ engineering blogs.

Netflix: one database per need

With 300+ million subscribers across 190+ countries, Netflix is the textbook case. MySQL handles billing and subscriptions, where ACID and strong consistency are required. Apache Cassandra is the most strategic store: it holds viewing history and profiles, with a write-to-read ratio around 9:1 — exactly the workload Cassandra is optimized for, thanks to leaderless replication with no single point of failure. Elasticsearch powers search, customer support and log analysis. EVCache, a caching layer built on Memcached and replicated across all AWS regions, serves session and personalization data with very high hit rates. Apache Iceberg on S3 holds analytics and ML data. And Kafka connects it all, carrying hundreds of billions of events a day.

Uber: creativity under pressure

Uber’s trip data is time-series-like, write-heavy, geospatially indexed and needed globally with low latency. The most interesting answer is Schemaless: in 2014 the available document databases didn’t meet Uber’s reliability bar, so the team built a sharding layer on top of MySQL and used it as a document store. The lesson runs deep: “NoSQL” is a design pattern, not just a product category. For geospatial indexing Uber built and open-sourced H3, a hierarchical hexagonal grid: all six neighbors of a hexagon are equidistant from its center, ideal for “drivers near me” and per-zone surge pricing. Kafka as backbone, Hadoop as data lake, and Flink with Apache Pinot for real-time analytics complete the picture.

LinkedIn: tools that became industry standards

LinkedIn stands out for how many tools it invented and then open-sourced. Kafka was born there in 2010: the problem was dozens of point-to-point ETL pipelines, and every new data consumer needed yet another one. Jay Kreps’ insight was that a durable, ordered, distributed commit log that every consumer subscribes to could replace them all. Today LinkedIn moves trillions of messages a day across thousands of brokers. Alongside Kafka sit Espresso, the in-house document store for profiles and messaging (built on MySQL, with Kafka as replication transport), Pinot for the real-time OLAP behind “Who Viewed My Profile”, and Brooklin for CDC across heterogeneous stores.

Netflix, Uber and LinkedIn architectures compared: Kafka backbone, CDC, operational store, search and cache
Three companies, one blueprint: Kafka at the center, CDC for sync, consistency chosen per domain

Common patterns

PatternNetflixUberLinkedIn
Event backboneKafkaKafkaKafka (they built it)
CDC mechanismInto KafkaInto KafkaBrooklin → Kafka
Operational storeCassandraSchemaless (MySQL)Espresso (MySQL)
CacheEVCacheRedisCouchbase
Consistency strategyPer domainPer domainPer domain

What all three avoid

The anti-patterns they rejected are as instructive as the choices they made:

  • None of them uses a single database for everything.
  • None uses distributed two-phase commit at scale. Sagas, compensating transactions and eventual consistency replace it.
  • None does synchronous dual writes. CDC from the transaction log is the standard.
  • None applies uniform consistency. Billing strong, feed eventual, cache best-effort.

Above all, these architectures evolved over years. Starting simple and growing toward polyglot is the right approach. Designing five databases on day one is a trap.

What about a small business? A proportionate architecture

This is the part that matters to most readers. A small or mid-sized business isn’t Netflix and shouldn’t try to be. The path I recommend to clients is incremental:

Three-stage data architecture for small businesses: PostgreSQL alone, then search and cache, then Kafka and CDC
Grow in stages: add a specialized database only when a concrete pain signal appears
  1. Stage 1 — one solid relational database. PostgreSQL covers transactions, structured data, some JSONB, even geospatial data with PostGIS. For many companies this is the final stage, and that’s perfectly fine.
  2. Stage 2 — the first specialist. Add one when a specific signal appears: catalog search is slow or inaccurate (Elasticsearch), sessions weigh down the database (Redis), sensors generate millions of rows (InfluxDB), relationships become the heart of your questions (Neo4j). At this scale, sync can be a nightly orchestrated job.
  3. Stage 3 — the event backbone. Only once you have three or more specialized stores that must stay aligned in near real time does it make sense to bring in Kafka and CDC.

Checklist before adding a database

  • Which access pattern does the current database serve poorly? Can I measure it?
  • Which store will be the source of truth for this domain?
  • How will data sync: nightly batch, CDC, application events?
  • How much staleness can I tolerate, and for how long?
  • Who on the team will run it, monitor it and back it up?
  • What happens to users if this database goes down?

That last question hides an underrated benefit: a well-designed polyglot architecture improves fault isolation. If Elasticsearch goes down, search is temporarily unavailable but orders keep flowing. With a single database, one failure stops everything.

The full series map

The pieces of the Digital Stack 2026 series now fit together: each technology we covered has a precise spot on the map. Neo4j for relationships, Kafka to move events and sync via CDC, InfluxDB for time series, Airflow to orchestrate batch work, Grafana to make it all visible. Polyglot persistence isn’t one more technology — it’s the criterion that tells you which one to use, when and why.

If your current system shows any of the symptoms from the opening — ever-slower queries, search that can’t find things, duplicated data across systems that don’t talk — request a data and AI analysis. We’ll look at your real access patterns and build a proportionate roadmap: sometimes the answer is a new database, often it’s making better use of the one you already have.