Skip to content

How to Choose the Right Database

Core Concept LearningJuly 1, 20268 min readUpdated July 21, 2026

This guide is for engineers who know basic SQL and key-value access but need to justify a production database choice. By the end, you can evaluate one checkout workload across storage models, identify the first operational failure, and write a testable decision record. For the category map see Types of Databases; for SQL vs document/KV trade-offs see SQL vs NoSQL.

Data shape narrows the field, but it does not decide alone. Consistency, access patterns, latency under a stated load, regulatory boundaries, migration cost, and the team’s ability to back up and restore a service can dominate an elegant schema match.

Decision tree: data type → category → database
Decision tree: data type → category → database

Evaluate One Checkout Workload

Use the same workload for every candidate: create an order with five items, reserve inventory exactly once, read the customer’s last 20 orders, search products by text, and retain a receipt PDF. Assume 100 writes and 1,000 reads per second at peak, one primary region, and a requirement that a paid order never appear unpaid because of a stale read.

PostgreSQL fits order and inventory transactions because constraints and atomic updates protect invariants. A document store can return an order aggregate conveniently, but cross-document inventory updates need transactions or a redesigned boundary. A key-value store can serve known-key order status, but “last 20 by customer” requires an explicit index. A search engine improves product discovery, and object storage owns receipt bytes; neither should become the authority for payment state.

The result is often a small portfolio, not one winner: one authoritative transactional store plus derived search/cache views and object storage. Consistency and access requirements decide which copy is authoritative; data shape only suggests representation.

Quick reference

  • Hold schema, request mix, correctness rules, and region count constant across candidates.
  • Measure p50/p95 latency, rejected writes, storage cost, restore time, and operator steps.
  • Mark each query that needs a secondary index, join, transaction, or derived projection.
  • Name the authoritative record; caches and search indexes may be stale.
  • Reject a candidate if the team cannot rehearse backup, restore, and schema migration.
Wrong fit: known-key storage forces a full scan
1node <<'NODE'2const orders = new Map([3  ["order:1", { customerId: "c-7", createdAt: 1 }],4  ["order:2", { customerId: "c-9", createdAt: 2 }],5  ["order:3", { customerId: "c-7", createdAt: 3 }],6]);7 8// "Last orders for c-7" has no key: every order must be inspected.9const result = [...orders.values()]10  .filter((order) => order.customerId === "c-7")11  .sort((a, b) => b.createdAt - a.createdAt)12  .slice(0, 20);13console.log({ inspected: orders.size, returned: result.length });14NODE
Relational fit: constraints plus indexed access
1sqlite3 :memory: <<'SQL'2PRAGMA foreign_keys = ON;3CREATE TABLE customers (id TEXT PRIMARY KEY);4CREATE TABLE orders (5  id TEXT PRIMARY KEY,6  customer_id TEXT NOT NULL REFERENCES customers(id),7  created_at TEXT NOT NULL8);9CREATE INDEX orders_customer_recent10  ON orders(customer_id, created_at DESC);11 12INSERT INTO customers VALUES ('c-7');13INSERT INTO orders VALUES14  ('o-1', 'c-7', '2026-07-21T12:00:00Z'),15  ('o-2', 'c-7', '2026-07-21T12:01:00Z');16SELECT id FROM orders17WHERE customer_id = 'c-7'18ORDER BY created_at DESC LIMIT 20;19 20-- Expected failure: duplicate order IDs violate the invariant.21INSERT INTO orders VALUES ('o-2', 'c-7', '2026-07-21T12:02:00Z');22SQL

Remember this

Consistency and access requirements decide which copy is authoritative, not data shape — the same checkout workload run against every candidate exposes that faster than any feature-list comparison.

Structured Data: Relational Databases

Relational databases store data in tables, can enforce referential integrity, and support transactions across related records. Those mechanisms are useful when invariants such as “inventory cannot be reserved twice” matter more than optimizing one isolated access path.

Use a relational model when the domain maps to constrained records and joins: user accounts, orders, invoices, and inventory. ORMs can help application integration, but generated queries, migrations, and transaction boundaries still need review.

Relational — all platforms
Relational — all platforms

AWS

  • RDS
  • Aurora

Azure

  • Azure SQL Database

Google Cloud

  • Cloud SQL
  • Cloud Spanner

Cloud Agnostic

  • PostgreSQL
  • MySQL
  • SQL Server
  • Oracle
  • CockroachDB

Quick reference

  • RDS and Aurora provide managed relational options on AWS; compare engine compatibility, failover, and cost.
  • Cloud Spanner can provide externally consistent distributed transactions; validate its model and operational cost against the workload.
  • PostgreSQL is a common portable starting point with broad provider support, not a universal answer.
  • Avoid relational stores for unstructured blobs, high-velocity time-series, or graph traversals.

Remember this

Choose relational when your schema is stable and transactions must be correct.

Structured Data: Columnar Stores

Columnar databases flip the storage model: instead of storing rows together, they store columns together. That makes aggregations — SUM, AVG, COUNT over millions of rows — dramatically faster and cheaper because the engine reads only the columns you query.

These are analytics engines, not application databases. Do not use them for OLTP workloads with frequent single-row updates. They shine in data warehouses, BI dashboards, log analytics, and batch reporting pipelines.

Columnar — analytics platforms
Columnar — analytics platforms

AWS

  • Redshift

Azure

  • Azure Synapse Analytics

Google Cloud

  • BigQuery

Cloud Agnostic

  • Snowflake
  • Databricks
  • Hive

Quick reference

  • BigQuery is serverless — you pay per query, which suits variable analytics workloads.
  • Snowflake and Databricks work across clouds, ideal for teams avoiding vendor lock-in.
  • Redshift and Synapse require cluster sizing — plan capacity and cost upfront.
  • Pair columnar stores with ETL pipelines (dbt, Airflow) to keep data fresh.

Remember this

Use columnar for scan-heavy analytics; avoid making it the transactional authority unless the product explicitly supports that workload.

Unstructured Data: Blob & Object Storage

Not everything is a table row. Images, videos, PDFs, backups, ML model artifacts, and raw log files are unstructured blobs — binary objects accessed by key, not by SQL query.

Object storage is designed for durable, high-scale object access, but every service has quotas, request costs, consistency semantics, and regional failure modes. Use it as the system of record for receipt bytes, then reference an object key—not a permanent public URL—from transactional metadata.

Blob / object storage
Blob / object storage

AWS

  • S3

Azure

  • Blob Storage

Google Cloud

  • Cloud Storage

Cloud Agnostic

  • HDFS

Quick reference

  • S3 tiers (Standard, Infrequent Access, Glacier) let you optimize cost by access frequency.
  • Enable versioning and lifecycle policies to protect against accidental deletes.
  • HDFS remains relevant in Hadoop/Spark on-premise environments.
  • Prefer object storage for large files; small transactional blobs can be reasonable when atomicity or operational simplicity outweighs database growth.

Remember this

Files belong in object storage. Keep only metadata in your database.

Semi-Structured: Key-Value & In-Memory

Semi-structured data does not fit rigid tables but still has identifiable keys. Session tokens, user preferences, feature flags, shopping carts, and rate-limit counters all map naturally to key-value access patterns.

In-memory layers can absorb repeated reads in front of an authoritative store. Their latency depends on network, payload, commands, persistence, and load; benchmark the actual path. Redis is one common choice, but it does not remove the need to define stale-read and eviction behavior.

Semi-structured branches
Semi-structured branches

AWS

  • DynamoDB
  • ElastiCache

Azure

  • Cosmos DB
  • Azure Cache for Redis

Google Cloud

  • Bigtable
  • Memorystore

Cloud Agnostic

  • Redis
  • RocksDB
  • Memcached
  • Hazelcast
  • Ignite

Quick reference

  • DynamoDB can scale to high throughput when keys and capacity are designed correctly; test throttling and hot partitions on your access pattern.
  • Cosmos DB offers multiple consistency levels and APIs (document, graph, table) in one service.
  • Redis supports strings, hashes, lists, sets, sorted sets, and pub/sub — far more than a simple cache.
  • Define TTLs on cached data to prevent stale reads and unbounded memory growth.

Remember this

Use key-value access for known-key lookups; use memory tiers only when measured latency needs justify staleness and eviction risk.

Semi-Structured: Wide Column & Document

When a single key is not enough, richer data models may fit. Document databases store aggregate-shaped records with evolving schemas; wide-column stores distribute partition-key-driven datasets with tunable consistency.

Document stores suit aggregate reads; wide-column stores suit workloads designed around known partition keys. Pick from measured query and consistency needs, not popularity or a named company’s scale.

Semi-structured branches
Semi-structured branches

AWS

  • DocumentDB
  • Keyspaces

Azure

  • Cosmos DB

Google Cloud

  • Firestore
  • Bigtable

Cloud Agnostic

  • MongoDB
  • Couchbase
  • Cassandra
  • HBase
  • ScyllaDB

Quick reference

  • DocumentDB is AWS's MongoDB-compatible managed service — good for teams already on MongoDB.
  • Firestore offers real-time sync for mobile and web apps with offline support.
  • Cassandra's partition key design is critical — get it wrong and queries become full scans.
  • Document stores trade join flexibility for horizontal scale and schema freedom.

Remember this

Documents for flexible schemas. Wide-column for write-heavy distributed scale.

Semi-Structured: Graph, Time-Series, Ledger & Geospatial

Some workloads benefit from dedicated indexes and execution models. Graph databases traverse relationships; time-series databases partition and compress timestamped data; ledgers preserve append-oriented audit evidence; geospatial engines index location. A specialized engine can improve a representative query, but it adds another service to secure, migrate, back up, and monitor.

SQL recursive queries and partitioned time-series tables can remain adequate at meaningful scale. Move only after a reproducible workload shows unacceptable latency, cost, or operational complexity—not because the data has a graph or timestamp in it.

AWS

  • Neptune
  • Timestream

Azure

  • Cosmos DB
  • Azure SQL Ledger

Google Cloud

  • Bigtable
  • BigQuery

Cloud Agnostic

  • Neo4j
  • InfluxDB
  • TimescaleDB
  • PostGIS
  • Hyperledger Fabric
  • TigerGraph

Quick reference

  • Neptune supports property graphs and RDF — choose based on your query language (Gremlin vs SPARQL).
  • TimescaleDB extends PostgreSQL with time-series hypertables — a gentle migration path for teams on Postgres.
  • For immutable audit ledgers on AWS, use Aurora with audit logging or Hyperledger Fabric — AWS QLDB was retired in July 2025.
  • PostGIS adds geospatial indexing to PostgreSQL — ideal if you already run Postgres.
  • For cryptographically verifiable audit trails across clouds, Hyperledger Fabric is the portable standard.

Remember this

Use purpose-built engines for graphs, metrics, audit trails, and location data.

Operate the Failure Before Choosing

In the checkout workload, the search projection falls 12 minutes behind after its change-data-capture consumer loses credentials. Customers can still pay, but newly added products disappear from search. The root cause is not the search engine’s data model; it is a broken replication boundary between the authoritative database and a derived index.

Detect the incident with projection-lag and consumer-error alerts. Keep checkout reads on the transactional store, restore credentials, and replay events from the last committed offset into a versioned index. Compare document counts and sampled product versions, then atomically switch the search alias. If the log cannot replay, rebuild from an authoritative snapshot and reconcile updates written during the rebuild.

Run an equivalent recovery drill for each candidate: kill a node, revoke a credential, fill a quota, and restore a backup. A database that wins a schema debate but fails your recovery-time objective is the wrong operational choice.

Zoom into one database choice tested by a migration rehearsal
Zoom into one database choice tested by a migration rehearsal

Quick reference

  • Trigger: expired CDC credential; symptom: stale search while checkout remains healthy.
  • Detection: consumer errors plus current time minus latest indexed event timestamp.
  • Recovery: replay to a new index, reconcile counts and versions, then switch the alias.
  • Prevention: credential rotation tests, replayable log retention, and an owned runbook.
  • Decision rule: consistency, access, recovery, and team operations can outweigh data-shape elegance.

Remember this

A stale search index is a broken replication boundary, not a database engine problem — checkout stays healthy on the authoritative store while the derived projection replays from the last committed offset.

Key takeaway

There is no universal best database. Use data shape to build a shortlist, then let authoritative consistency, access patterns, failure recovery, compliance, migration, and operator skill decide. Add specialized stores only for a measured query or boundary, and keep their relationship to the source of truth explicit.

Practice (30 min): implement the checkout schema in two candidates. Seed 1,000 orders; test create-order, last-20-orders, and duplicate inventory reservation; record query plans or consumed capacity. Then stop a dependency or revoke a credential, restore service, and prove no duplicate reservation occurred. Write the evidence and your rejection threshold in a one-page ADR.

Share:

Related Articles

As relational databases grow beyond millions to billions of rows, single-table query performance degrades due to massive

Read

Approximate Nearest Neighbor (ANN) search is the engine behind Retrieval-Augmented Generation (RAG) and semantic search.

Read

Relational databases like PostgreSQL excel at Online Transaction Processing (OLTP)—handling frequent single-row reads, u

Read

Keep learning

Follow a structured path or browse all courses to go deeper.