SQL vs NoSQL vs Object Storage: How to Choose Storage
The three kinds of storage (SQL, NoSQL and blob storage) and how to choose: data model, transactions, consistency, query needs, "just use Postgres" and hybrid designs.
Storage is the backbone of a scalable system. It isn't just somewhere to put data: it decides how fast you can read it, how safely it's kept and how far it can grow. Most designs pick from three kinds of storage: SQL (relational) databases, NoSQL databases and blob/object storage. This page explains what each is for, then how to choose between SQL and NoSQL, which is one of the first decisions in almost every design.
What storage does in a system
Think of a huge, carefully organized library. The library is the storage system and the books are the data; how the shelves are organized decides how quickly you find a book. Storage serves four purposes:
- Persistence: data outlives the process that created it: user profiles, transaction records, session data.
- Performance: read and write speed directly shape how responsive the application feels.
- Scalability: as the application grows, so does its data, and storage must grow without slowing down. See scalability.
- Reliability and availability: data must be protected against loss and stay reachable through failures. See replication.
Three kinds of storage
SQL (relational) databases
The traditional choice for structured data: tables that relate to each other through primary and foreign keys, supporting complex queries and transactions. Use them for complex transactions that need ACID guarantees, for systems where data integrity and relationships are crucial, and when a structured schema and SQL's querying power help. See relational databases.
NoSQL databases
Built to store and manage semi-structured and unstructured data, in several forms: key-value, document, column-family and graph. Known for flexibility, scalability and performance with large volumes. A document database might store a user together with their orders:
{
"userID": "2",
"name": "Bob",
"orders": [{ "orderID": "102", "details": "Order details here..." }]
}Use them when you need high scalability and a flexible data model, when the data structure changes fast during development, or for large volumes of unstructured or semi-structured data. See NoSQL databases.
Blob / object storage
Blob (Binary Large Object) or object storage holds unstructured files such as images, videos, audio, backups and logs. Each object bundles the data, its metadata and a unique identifier, and is reached over HTTP/HTTPS. It scales almost without limit. Use it for large media files, backups and disaster recovery, and content served straight to browsers (often through a CDN). See object storage.
| Feature | SQL databases | NoSQL databases | Blob/object storage |
|---|---|---|---|
| Data structure | Structured | Semi-structured / unstructured | Unstructured |
| Scalability | Vertical (horizontal with sharding work) | Horizontal | Horizontal |
| Transactions | ACID | Varies | Not applicable |
| Querying | Complex queries | Flexible, schema-less queries | Metadata-based |
| Typical use | Traditional web apps, ERP systems | Big data, real-time analytics | Media storage, backups |
Choosing the right storage
You wouldn't use a hammer on a screw, and you wouldn't use a key-value store for relational data that needs complex joins. The choice affects performance and scalability, and also complexity and cost. Ask:
- Data model: is the data structured, semi-structured or unstructured? Does it fit neatly into tables or is it free-form?
- Access patterns: more reads or more writes? Do you need fast reads, fast writes, or both?
- Scale: how much data now and later? Do you need to scale out across machines or up on one machine?
- Consistency: do you need strong consistency, or is eventual consistency acceptable?
- Cost: capacity, transaction rates and operational overhead give each option a different cost profile.
SQL vs NoSQL: the core differences
SQL databases store data in tables with a fixed schema and let you query it flexibly with joins and transactions. NoSQL is an umbrella term for non-relational stores that trade some of that flexibility for easier horizontal scaling, flexible schemas or a data model matched to a specific access pattern. Neither is better in general; the right choice follows from how the data is read and written.
| SQL (relational) | NoSQL | |
|---|---|---|
| Data model | Tables, rows, foreign keys | Key-value, documents, wide columns or graphs. See NoSQL database types |
| Schema | Defined up front, enforced by the database | Flexible; often enforced by the application |
| Queries | Ad-hoc SQL: joins, aggregations, any filter with the right index | Mostly lookups by key or a few designed access paths; limited joins |
| Transactions | Multi-row, multi-table ACID | Often single-item atomicity; some offer multi-item transactions with limits |
| Scaling writes | One primary per database; sharding is extra work | Built-in partitioning across many nodes |
| Consistency | Strong by default | Often eventual or tunable. See CAP theorem |
| Examples | PostgreSQL, MySQL, SQL Server, Oracle; Spanner, CockroachDB | DynamoDB, Cassandra, MongoDB, Redis, Neo4j |
The same data, modeled two ways
The relational version stores each fact once and can answer questions nobody planned for ("revenue by product category by month"). The document version reads a whole order in one fast lookup but duplicates user details and makes cross-order queries harder. See normalization vs denormalization.
How to choose between SQL and NoSQL
Most of the time, either works
Many systems could be built on either, and the choice often comes down to team familiarity or existing infrastructure. The popular saying "Just use Postgres" captures this: beginners and experts alike end up recommending PostgreSQL, while the people in the middle agonize over object stores, key-value stores, event sourcing, time-series and graph databases. The line is blurry anyway: PostgreSQL supports NoSQL-style JSON fields that you can index and query.
-- PostgreSQL: a flexible JSON column inside a relational table
CREATE TABLE products (
id bigserial PRIMARY KEY,
name text NOT NULL,
attrs jsonb -- different keys per product category
);
CREATE INDEX products_attrs ON products USING gin (attrs);
SELECT name FROM products WHERE attrs @> '{"waterproof": true}';This is especially true for small systems: if QPS is low, pick the simpler option and don't over-engineer. PostgreSQL covers the vast majority of use cases, including JSON data and horizontal-scaling extensions.
If you need transactions, go with SQL
SQL databases suit cases that need strong consistency and ACID transactions: banking systems and e-commerce checkout flows need strict transactional integrity.
Then check the data model, consistency and queries
| Question | Points to SQL | Points to NoSQL |
|---|---|---|
| Data model: is it structured and relational? | Structured, relational data | Semi-structured or unstructured data |
| Consistency vs availability | Strong consistency required (financial transactions) | Availability matters more (content feeds) |
| Query requirements | Complex queries, relational operations, JOINs | Fast lookups, simple key-value operations |
When SQL is the better default
- Data is relational: many entities that reference each other (users, orders, products, payments).
- You need transactions across several rows or tables: money, inventory, bookings.
- Access patterns will change, or analysts need ad-hoc queries.
- The data fits on one primary (with replicas), which with modern hardware is often terabytes and thousands of writes per second.
PostgreSQL is a strong default for a new system. It handles relational data, JSON documents (jsonb), full-text search and geospatial queries well enough for many products, and you can move specific workloads elsewhere when numbers demand it.
When NoSQL is the better fit
- Massive scale with simple access patterns: billions of items read and written by key (sessions, user timelines, IoT readings, shopping carts).
- Write-heavy workloads that outgrow a single primary: append-heavy event or time-series data on wide-column stores like Cassandra (millions of writes per second).
- Flexible or evolving structure: product catalogs where each category has different attributes, or schema changes deploying daily (document stores like MongoDB).
- Specialized models: relationship traversal (graph databases), sub-millisecond caching and counters (Redis), search (Elasticsearch).
- Predictable latency at any scale with managed operations (DynamoDB).
Hybrid systems: several databases in one design
Modern systems commonly use several databases, even of different types, each for the component it fits (polyglot persistence):
- E-commerce: PostgreSQL for orders and transactions, Redis for session storage and caching, MongoDB for the product catalog, Elasticsearch for product search.
- Social network: PostgreSQL for user information, a graph or wide-column store (Neo4j or Cassandra) for friendship relations, Redis for pending user feeds.
Keep the stores in sync with events or change data capture rather than dual writes from application code.
A checklist for interviews
- List the access patterns: what queries run, how often, with what latency.
- Estimate volume and write rate. See back-of-the-envelope estimation.
- Identify invariants that need transactions (no double booking, balance never negative).
- Pick the simplest store that serves those patterns at that scale; use different stores for different parts: Postgres for orders, Redis for sessions, Elasticsearch for search, S3 for media.
NoSQL stores are designed around known queries. In DynamoDB or Cassandra you design tables per query, and a new question can mean a new table and a backfill. That's the price of their scalability.
Where it’s used
Stores core relational data (users, media metadata, likes) in sharded PostgreSQL, and uses Cassandra for high-volume feed and activity data.
Moved many internal workloads from Oracle to DynamoDB for predictable performance at scale, while keeping relational stores where transactions matter.
Built Schemaless/Docstore on top of MySQL to get a scalable key-document store, showing the line between SQL and NoSQL is often an implementation detail.
Start on PostgreSQL or MySQL and add Redis, a search engine and object storage as specific needs appear.
In an interview
- Justify the database from access patterns and scale, not fashion: "orders need transactions, so Postgres; the activity feed is append-heavy and read by key, so Cassandra".
- For small or low-QPS systems, choose the simpler option and say you'd revisit at scale.
- Use different stores for different data and say how they stay in sync (events, CDC).
- If you pick NoSQL, show the key or partition design that serves each query.
- Mention that relational databases scale further than people think with replicas and caching before sharding is needed.
Further reading
- Just use PostgresEthan McCue
- JSON typesPostgreSQL documentation
- JSON functions and operatorsPostgreSQL documentation