NoSQL & Beyond

Expert · 17 min read · ▶ live playground · ✦ checkpoint

Relational databases are powerful because tables, keys, joins, and transactions give data a clear skeleton. But not every problem starts as a neat grid. NoSQL is a broad family of non-relational database styles, meaning they do not organize everything around SQL tables, often to make one kind of read or write very fast or flexible.

This lesson uses plain Python dictionaries and lists to model the ideas. They are not real database servers such as Redis or MongoDB. They are small maps on the whiteboard so you can see what those tools are optimizing for.

Keys to values

A key-value store is a database style that stores one value under one key, like a giant labeled cubby wall. You hand it a key such as "session:mina", and it gives back the value stored there.

That sounds like a Python dictionary because the mental model is close. Real key-value databases add server features that a dictionary does not have, such as saving data durably, sharing it with other programs, and spreading work across machines. The core access pattern is still: "I know the key, give me the value."

session_store = {}
 
session_store["session:mina"] = {
    "reader": "Mina",
    "cart": ["Practical Python", "Data Stories"],
}
session_store["session:ravi"] = {
    "reader": "Ravi",
    "cart": ["Clean APIs"],
}
 
for key in ["session:mina", "session:ravi"]:
    session = session_store[key]
    print(f"{session['reader']}: {len(session['cart'])} saved book(s)")

Mina: 2 saved book(s)
Ravi: 1 saved book(s)

A cache is storage used to keep expensive-to-rebuild answers close by for quick reuse. Key-value stores are common cache tools because the lookup is direct: key in, value out.

The weakness follows the same shape. If you do not know the key, a key-value store is the wrong starting point. Asking "which sessions contain Clean APIs?" means scanning values unless the system has another structure built for that question.

Nested records

A document store is a database style that stores each record as a nested document instead of splitting every fact into rows across tables. A document is a self-contained record with fields, often shaped like JSON, such as one member profile with preferences and borrowed books inside it.

Think of a document store as a shelf of filled-out packets. Each packet can carry nested sections, and two packets do not have to be identical. That flexibility helps when records naturally arrive as nested data from web forms or APIs.

members = [
    {
        "name": "Mina",
        "city": "Mumbai",
        "preferences": {"format": "ebook", "topics": ["Python", "Data"]},
        "borrowed": [
            {"title": "Practical Python", "due": "2026-07-12"},
            {"title": "Data Stories", "due": "2026-07-18"},
        ],
    },
    {
        "name": "Ravi",
        "city": "Bengaluru",
        "preferences": {"format": "print", "topics": ["Web"]},
        "borrowed": [{"title": "Clean APIs", "due": "2026-07-10"}],
    },
]
 
for member in members:
    titles = [book["title"] for book in member["borrowed"]]
    print(f"{member['name']}: {', '.join(titles)}")

Mina: Practical Python, Data Stories
Ravi: Clean APIs

In SQL, that same information would probably become members, books, and loans tables joined by keys. In a document store, the borrowed-book snapshot can live inside the member document if that is how the app usually reads it.

Try it - query a document-shaped model

This playground is still plain Python. Change wanted_topic or add a new member with a different set of fields. The point is to feel document-shaped data before you meet a real document database.

python — playgroundlive
⌘/Ctrl + Enter to run

Notice the uneven fields: Mina has badges, Noor has newsletter, and Ravi has neither. A document store can allow that kind of record-by-record variation. That freedom is useful, but it also moves responsibility into your application code: your code must handle missing fields calmly.

Choosing SQL vs NoSQL

Do not choose a database by trend. Choose by the questions your application must answer and the promises your data must keep.

Choose SQL when:

  • Your data has clear relationships: members, loans, books, payments, orders.
  • You need joins to answer important questions.
  • You need strong rules around valid rows, foreign keys, and transactions.
  • You want a general-purpose default that future developers will understand.

Choose a key-value store when:

  • You already know the key for the thing you need.
  • The value is naturally fetched as one unit.
  • The data is temporary or cache-like, such as sessions, tokens, feature flags, or computed results.

Choose a document store when:

  • A record is naturally nested and usually read as one whole document.
  • The shape changes often across records.
  • You can design your queries around document fields instead of joins.

The sharpest question is not "SQL or NoSQL?" It is "what are my access patterns?" An access pattern is the regular way your application reads or writes data, like "load one user's profile by ID" or "list overdue loans by due date."

questions = [
    ("load session by token", "key-value"),
    ("list every overdue loan with member names", "SQL"),
    ("save one nested user preferences profile", "document"),
    ("transfer money between two accounts", "SQL"),
]
 
for question, likely_store in questions:
    print(f"{question}: consider {likely_store}")

load session by token: consider key-value
list every overdue loan with member names: consider SQL
save one nested user preferences profile: consider document
transfer money between two accounts: consider SQL

That last example matters. Consistency means the database keeps related facts from disagreeing after a change. If money leaves one account and enters another, both sides must succeed or both must fail. SQL databases are often chosen for that kind of transactional rule.

Beyond the first two

Key-value and document stores are only the first NoSQL shapes. A graph database stores data as things and links between them, useful when the connections are the main story. A search index is a database-like system optimized for finding and ranking text. A wide-column store groups very large table-like data by columns for high-scale workloads.

You do not need those tools on day one. You need the habit: start with the data shape, the query shape, and the correctness promises. Then pick the storage tool that fits.

Checkpoint

Answer all three to mark this lesson complete

You now have the database map: SQL tables, Python drivers, ORMs, and the first NoSQL shapes. Section 23 moves that persistence work into web development and APIs, where Python programs receive web calls, talk to storage, and send useful responses back.

+50 XP on completion