Practice this topic in a realistic system design interview
Choosing a database is one of the first big system design decisions. It is also one of the hardest to undo later.
The database affects how you model data, how you query it, how you scale writes, how you recover from failures, and how much operational work your team takes on.
There is no best database for every system. There is only a good fit for a specific data shape, workload, and set of failure goals.
This chapter walks through the major database categories used in modern systems. For each one, we will look at what it is good at, what it is bad at, and when you should consider it. The goal is to choose from requirements, not from brand names.
Later chapters go deeper into relational, document, key-value, wide-column, graph, time-series, search, and vector stores, along with transactions and durability.
Relational databases were the default choice for decades, and they are still the right default for many applications. PostgreSQL, MySQL, SQL Server, and Oracle handle a huge range of production workloads well.
New database types appeared because systems started hitting different limits.
Some workloads need to spread reads and writes across many machines. Some need to keep working even when a machine, zone, or region fails. Some data changes shape often or has many optional fields.
Other problems need special indexes. Text search, graph traversal, time-range queries, and vector similarity do not behave like a normal row lookup.
Global applications may also need data close to users for speed. And many teams prefer managed services that hide most of the cluster operations.
Newer databases did not replace relational ones. They appeared because different workloads reward different storage designs.
Databases fall into a few broad families. Each family is shaped around a different data model and a different way of reading or writing data.
The diagram below groups the main categories and lists common systems in each group.
These categories overlap in practice. PostgreSQL can store JSON, run full-text search, and support vector indexes through extensions. DynamoDB can behave like a document store. Elasticsearch stores documents, but it is usually a search index, not the source of truth.
Use categories to reason about trade-offs, not as strict boxes.
Relational databases store data in tables with rows and columns. Each table has a schema, which means the database knows what fields exist and what types they should have.
Relationships between tables are usually represented with primary keys and foreign keys. SQL is the query language. It supports joins, filters, grouping, sorting, indexes, and transactions.
The schema is checked when data is written, so many bad rows are rejected before they enter the database. A single primary database can provide strong consistency. Distributed behavior depends on how the database is deployed.
Scaling usually starts with a larger machine and read replicas. Sharding is usually saved for later, when one primary can no longer keep up, because splitting relational data across machines adds real complexity.
Relational databases are often the best starting point for a new application because they provide strong correctness guarantees, flexible querying, mature tooling, and a well-understood operating model.
Foreign keys connect rows across tables. Here, the orders table points back to the users table through user_id.
Choose a relational database when you need transactions across related records and your data has clear relationships. It also fits when you need flexible queries, reports, or analytics over operational data, and when correctness matters more than maximum write speed.
And when you are unsure which database to choose and have no strong reason to start elsewhere, relational is the safe place to begin.
For most product systems, a relational database is the sensible default source of truth. The source of truth is the place where the official, durable record lives.
Key-value stores use the simplest database model: a key maps to a value.
The database does not need to understand the value. It only needs to store it, fetch it, update it, or delete it by key. Many key-value stores also support counters, expiration times, and conditional updates.
The value is usually a black box to the database, so there is no schema to enforce. Consistency depends on the system and its settings. Partitioning works well as long as keys spread evenly across nodes.
This simplicity is why key-value stores can be so fast.
Each key points directly to a value. The examples below show user records, sessions, cached products, and counters, all reached by a single key.
Key-value stores fit a handful of common jobs: caching expensive reads; storing sessions, tokens, rate-limit counters, or feature flags; and maintaining counters, leaderboards, or other small pieces of state.
What ties these together is simple: the application already knows the key it wants, so every access is a direct lookup.
A key-value store is often used next to a primary database, not instead of one. Redis may cache user profiles while PostgreSQL remains the durable source of truth.
Document databases store records as JSON-like documents grouped into collections. A document can contain nested objects, arrays, and optional fields.
This works well when the stored data looks like the objects your application already uses.
Document databases are useful when data is naturally nested and most reads fetch one whole thing, such as a product, profile, article, or configuration object. Queries can target document fields, nested fields, and indexes.
The schema is flexible, often with optional validation. Many systems support strong reads and even multi-document transactions, but usually with limits. Scaling happens by partitioning or sharding documents across machines.
A collection holds self-contained documents that can nest objects and arrays. The two products below share a general shape, but each document can carry fields that only make sense for that product.
That flexibility is helpful, but it still needs discipline. A document database with no schema habits eventually becomes hard to reason about.
A document database makes sense when your data is nested and most reads and writes touch one document at a time. It also fits when the schema changes often but the domain still has a recognizable shape. Catalogs, profiles, content systems, forms, configuration stores, and event-like records often fit this model.
Wide-column stores are built for very large datasets spread across many machines. They split data by row key and store columns in groups called column families.
Rows can have different columns, so a row only stores the columns it needs. This is useful for sparse data, where many fields are empty for many records.
These systems are usually chosen for very high write volume, huge data retention, and predictable queries by key. Queries are designed around partition keys and sort keys, not arbitrary fields.
Column families are planned ahead of time, but individual columns within them can be sparse. Consistency is often adjustable per query, with exact behavior depending on the database. The design assumes many machines and heavy writes from day one.
Rows are addressed by a row key, and each row holds only the columns it needs. The two rows below carry different columns, which shows the sparse layout these stores rely on.
Wide-column stores are worth their operational cost when you have very high write volume and predictable, key-based queries. They fit large volumes of event, telemetry, audit, or time-ordered data. They also fit systems that must keep working through failures and can be designed around the database's consistency model.
Wide-column stores punish vague query requirements. Write down the exact queries the application must serve before choosing one. If you need flexible querying, use a different system or add an analytical store.
Graph databases model data as nodes and edges. Nodes are things, such as people, companies, accounts, or products. Edges are relationships between those things, such as FRIENDS_WITH, WORKS_AT, or OWNS.
Both nodes and edges can store properties.
Graph databases are designed for questions where relationships are the main thing you care about. Queries are written as traversals or pattern matches in languages such as Cypher, Gremlin, or SPARQL.
The schema is usually flexible, with optional constraints in many systems. A single graph database typically gives strong consistency. Distributed behavior varies, and scaling across machines is harder than simple key-based partitioning because relationships often cross machine boundaries.
Nodes hold entities, and labeled edges hold relationships. Below, people connect to each other, to a shared skill, and to an employer. Each edge names the relationship.
A graph query can naturally ask: "Find people connected to Alice within two hops who know Python and work at the same company."
Graph databases are the right choice when relationships are the main thing you query. They fit social graphs, followers, professional networks, and permission systems. They are also useful for fraud detection and other suspicious-pattern discovery.
The same strengths carry over to relationship-based recommendations, knowledge graphs, dependency analysis, data lineage, network topology, routing, and infrastructure relationships.
Some databases are built around one dominant access pattern. They are often excellent secondary systems, fed from a primary database or an event stream.
Time-series databases store timestamped measurements such as metrics, sensor readings, financial ticks, and application telemetry. They are optimized for high write volume, time-range queries, compression, retention policies, and rollups.
Use when: queries are mostly time-range filters, summaries, downsampling, and retention over timestamped data.
Search engines use inverted indexes and ranking algorithms to find relevant text quickly. They are used for product search, document search, log search, autocomplete, and faceted filtering.
Use when: users need ranked text search, filtering, highlighting, autocomplete, or log exploration.
Search engines are usually not the system of record. They are indexes built from another source of truth.
Vector databases store embeddings and search by similarity. An embedding is a list of numbers that represents the meaning of text, an image, or another piece of data.
Vector databases are used for semantic search, recommendations, image similarity, personalization, and retrieval-augmented generation.
Use when: similarity matters more than exact matching, such as "find documents that mean something close to this query."
Vector databases do not replace the source data. They store searchable representations of that data.
Database choice starts with the workload. Ask these questions before naming a technology:
Working through these questions in order points toward a category. The flowchart below routes the answers from the most common default, relational, down to more specialized stores.
Many mature systems use more than one database. This is sometimes called polyglot persistence, which simply means using different storage systems for different jobs.
This can be effective, but it is not free. Every extra database adds deployment work, monitoring, backups, permissions, schema changes, data pipelines, and new ways things can fail.
A good rule for beginners: start with one durable source of truth, usually relational unless requirements clearly point elsewhere. Add specialized databases only when a real access pattern justifies the extra operational cost.
Different databases exist because different workloads need different trade-offs. Relational databases are the default for structured data, transactions, and integrity. Key-value stores are best for simple, fast lookup by key. Document databases fit nested data with fields that evolve.
Wide-column stores support huge, write-heavy workloads with predictable queries. Graph databases are built for relationship traversal. Time-series, search, and vector databases optimize for their own specialized query patterns.
The practical skill is reading requirements and mapping them to storage behavior: data model, query pattern, consistency, scale, durability, and operations. Product names come after that thinking, not before it.
10 quizzes