Data Architecture Microservices

Polyglot Persistence

Using multiple database technologies within a single application — choosing relational, document, graph, cache, and time-series stores for the access patterns that fit each, and managing consistency across heterogeneous stores.

⏱ 9 min read

What it is

Polyglot persistence is the practice of using different database technologies — each selected for its fit with a specific access pattern or data model — within a single application or system. The term was coined by Martin Fowler and Neal Ford in 2011. Rather than forcing all data into a single relational database, each domain's data is stored in the store that best serves its read/write patterns: relational databases for transactional consistency, document stores for flexible schemas, key-value stores for low-latency lookups, graph databases for relationship traversal, and time-series databases for metric data.

Common combinations: PostgreSQL for user accounts and orders (ACID transactions), MongoDB/DynamoDB for product catalog (flexible schema, high read throughput), Redis for session data and feature flags (sub-millisecond access), Elasticsearch for full-text product search, Neo4j for recommendation graphs, and InfluxDB/Prometheus for time-series metrics.

Why it exists

No single database type is optimal for all access patterns. A relational database with foreign key constraints and ACID transactions is ideal for financial records but wasteful for session state that is read-heavy, never joined, and can tolerate losing data on cache eviction. A graph database that traverses relationship paths in milliseconds degrades to seconds when the same traversal is expressed as recursive SQL JOINs. Polyglot persistence evolved alongside the microservices architecture movement: once a monolith is decomposed into services, each service can independently choose the storage technology that fits its domain, rather than all services sharing a single monolithic database.

When to use

  • When different domains within an application have genuinely different access patterns — e.g., financial transactions require ACID, but user activity feeds require only eventual consistency and sequential writes.
  • When full-text search is a core feature — embedding search in a relational database is functional but Elasticsearch provides superior relevance tuning, faceting, and scaling.
  • When you need sub-millisecond latency for frequently accessed data (session tokens, rate-limit counters, feature flags) that doesn't need durability — Redis eliminates the need to hit a relational DB for every request.
  • When your data is a graph (social network, fraud detection, knowledge graph, supply chain) — native graph databases express and traverse relationships 10–100x faster than equivalent recursive SQL.
  • When the team has matured beyond a monolith and service boundaries are stable — polyglot persistence increases operational complexity that is only justified once the domain model is well-understood.

When not to use

  • Don't adopt polyglot persistence in early-stage products where the domain model is still evolving — the operational overhead of multiple database systems outweighs the benefits when schema is changing weekly.
  • Don't introduce a new database technology to solve a problem that can be solved by a feature of your existing database (PostgreSQL has JSONB, full-text search, and array types that handle many non-relational use cases).
  • Don't use polyglot persistence without clear ownership per database — if all services share all databases, you've created a distributed monolith with the worst properties of both architectures.
  • Don't underestimate operational overhead — each additional database technology adds backup procedures, monitoring, on-call knowledge, patching, and cost.

Typical architecture


  E-Commerce Polyglot Persistence:

  ┌──────────────────┐   ┌─────────────────┐   ┌──────────────────┐
  │  Order Service   │   │ Catalog Service  │   │  Session Service │
  │  PostgreSQL      │   │  MongoDB         │   │  Redis           │
  │  ACID txns       │   │  Flexible schema │   │  Sub-ms reads    │
  │  Normalized      │   │  High read TPS   │   │  Ephemeral data  │
  └──────────────────┘   └─────────────────┘   └──────────────────┘
         │                       │                       │
         │        ┌──────────────▼──────┐                │
         │        │   Search Service    │                │
         │        │   Elasticsearch     │                │
         │        │   Full-text search  │                │
         │        │   Faceted filtering │                │
         │        └─────────────────────┘                │
         │                                               │
  ┌──────▼─────────────────────────────────────┐         │
  │            Recommendation Service           │         │
  │            Neo4j (Graph)                    │         │
  │            "Customers who bought X also..." │         │
  └─────────────────────────────────────────────┘         │
                                                          │
  Consistency across stores: eventual, via domain events (Kafka)
          

Pros and cons

Pros

  • Optimal fit: each access pattern uses the database model that serves it most efficiently, reducing over-engineering workarounds.
  • Independent scalability: the read-heavy product catalog (MongoDB) can be scaled separately from the write-heavy order store (PostgreSQL) without affecting each other.
  • Service autonomy: teams own their data store choices and can evolve them without negotiating with other teams sharing a monolithic database.
  • Performance at the extremes: Redis for sub-millisecond session reads; Elasticsearch for relevance-scored full-text search — neither is achievable in a relational database at scale.
  • Resilience: a failure in the Redis cache doesn't take down the order database; fault isolation between stores limits blast radius.

Cons

  • Operational complexity: each database system requires dedicated expertise, monitoring, backup strategy, and SLA management.
  • No cross-store ACID transactions: operations spanning multiple stores must use sagas or compensating transactions with eventual consistency.
  • Data consistency challenges: when the same logical entity (e.g., a product) exists in both MongoDB (catalog) and Elasticsearch (search index), keeping them synchronized requires reliable event-driven pipelines.
  • Cost: licensing, hosting, and operational costs multiply with each additional database technology.
  • Reporting complexity: cross-domain analytics require ETL pipelines into a data warehouse since there's no single queryable store across all domains.

Implementation notes

Synchronization between polyglot stores is typically handled through domain events. When an order is created in PostgreSQL, an event is published to Kafka. The search indexing service consumes the event and updates Elasticsearch. The recommendation service updates Neo4j. This ensures eventual consistency without direct service-to-service calls. Use the Transactional Outbox pattern to guarantee that the event is published if and only if the primary database write succeeds — write the event to an outbox table in the same PostgreSQL transaction as the business data, then poll or use CDC (Debezium) to relay it to Kafka.

Before introducing a new database technology, evaluate PostgreSQL's native capabilities: JSONB for document storage, full-text search with tsvector, array columns, lateral JOINs for graph-like queries, and TimescaleDB as a PostgreSQL extension for time-series. These features eliminate the polyglot overhead for many use cases. Introduce a new database technology only when its category provides a 5–10x improvement in the specific access pattern that matters, or when the domain model genuinely cannot be expressed in relational form.

Common failure modes

  • Inconsistent state across stores: The product catalog in MongoDB is updated but the synchronization pipeline to Elasticsearch fails silently; users search for a product that no longer exists or can't find a product that was just added.
  • Technology sprawl: Every team adds a new database technology for every project; the organization accumulates 12 different database technologies with no deep expertise in any of them and no standardized observability.
  • Shared database breaking encapsulation: Services that "own" different databases still read each other's databases directly for reporting; the benefit of independent data ownership is lost while the operational complexity of multiple databases is retained.
  • Cache/DB inconsistency: Redis cache is not invalidated when PostgreSQL data changes; stale data is served for hours until TTL expiry, causing incorrect business logic (e.g., showing an out-of-stock item as available).
  • Saga failure without compensation: A multi-step saga writes to PostgreSQL (reserve inventory), then Redis (update session), then MongoDB (create order); the MongoDB write fails; compensation logic was not implemented; inventory is reserved but no order exists.

Decision checklist

  • Does the access pattern genuinely require a different database category, or can PostgreSQL's native features (JSONB, full-text, TimescaleDB extension) satisfy the requirement?
  • Is service/domain ownership of each database clearly defined to prevent cross-service database coupling?
  • Is there a synchronization strategy (Transactional Outbox + CDC, or event publishing) that guarantees consistency between stores?
  • Has the team assessed the operational overhead: backup, monitoring, on-call runbooks, and expertise for each additional database technology?
  • Are cache invalidation strategies defined for every Redis-cached entity, including TTLs and event-driven invalidation?
  • Is there a cross-domain reporting strategy (data warehouse + ETL) since there's no single queryable store?

Example use cases

  • Social media platform: PostgreSQL for user accounts and authentication (ACID), Cassandra for activity feeds and timelines (high write throughput, time-ordered), Redis for online presence and notification counts (low latency), Neo4j for friend recommendations (graph traversal), Elasticsearch for user search.
  • IoT platform: PostgreSQL for device registration and configuration, InfluxDB for sensor telemetry time-series, Redis for real-time device state (last-seen, current readings), Elasticsearch for device log search.
  • Healthcare records system: PostgreSQL for structured patient records with HIPAA-compliant ACID guarantees, MongoDB for unstructured clinical notes and imaging metadata (flexible schema), Elasticsearch for clinical document search, Redis for session tokens with short TTL for security compliance.
  • Database Per Service — The microservices pattern that enables polyglot persistence by giving each service exclusive ownership of its data store.
  • Transactional Outbox — Ensures reliable event publishing when writing to primary store, enabling consistent synchronization to secondary stores.
  • CQRS — A write model in PostgreSQL and a read model in Elasticsearch or Redis is a common polyglot CQRS implementation.

Further reading