← Tutorials 🤖 AI 📓 Architect's Notebook ☁ AWS 📋 Cheatsheet 🗃 Databases 🚀 DevOps 🧩 DSA ❓ FAQ 🖥 Frontend ☕ Java 🍏 MongoDB 🐍 Python 🌿 Spring Boot 🏗 System Design 🏛 TOGAF
Tutorials › Databases
One hub for databases — foundations, a decision guide on which to use, and per-engine deep dives (MySQL, MongoDB, Cassandra, DynamoDB). ★ topics include visual diagrams.

What is a Database

🛢️ Databases · Foundations · 5 min read

A database is an organized collection of data, stored and accessed electronically, managed by a Database Management System (DBMS). The DBMS handles storage, retrieval, concurrency, integrity, and security so applications don't have to.

Why Use a Database (not files)

  • Querying — ask complex questions of the data (SQL or query APIs).
  • Concurrency — many users read/write safely at once.
  • Integrity — constraints and transactions keep data valid.
  • Durability & recovery — survive crashes; back up and restore.
  • Scale & performance — indexes, caching, replication, sharding.
💡 This hub covers the four engines you'll meet most: MySQL (relational), MongoDB (document), Cassandra (wide-column), and DynamoDB (key-value). The most valuable skill is knowing which to pick — see "Which Database to Use".

Database Types

🛢️ Databases · Foundations · 6 min read

Databases come in families, each optimized for a data shape and access pattern.

TypeStores data asExamplesBest for
Relational (SQL)Tables, rows, columnsMySQL, PostgreSQLTransactions, joins, structured data
DocumentJSON-like documentsMongoDB, CouchbaseFlexible schemas, nested data
Key-ValueKey → valueDynamoDB, RedisUltra-fast lookups, caching
Wide-ColumnRows with dynamic columnsCassandra, HBaseHuge write volume, time-series
GraphNodes & edgesNeo4j, NeptuneRelationships, recommendations
SearchInverted indexElasticsearchFull-text search, analytics
Time-seriesTimestamped pointsInfluxDB, TimestreamMetrics, IoT
💡 NoSQL ("Not Only SQL") spans document, key-value, wide-column, and graph. There's no "best" type — match the model to your data shape and access pattern (often you use several together → polyglot persistence).

SQL vs NoSQL

🛢️ Databases · Foundations · ★ In-depth · 10 min read

The fundamental database decision. SQL (relational) databases use fixed schemas, tables, and strong consistency; NoSQL databases trade some of that for flexibility and horizontal scale.

Side by Side — Visual

SQL (Relational) id | name | email (fixed columns) fixed schema · joins · ACID vertical scale · strong consistency MySQL · PostgreSQL · Oracle NoSQL { id, name, email, orders: [...], tags: [...] }flexible document flexible schema · no joins horizontal scale · BASE MongoDB · Cassandra · DynamoDB

Comparison

SQLNoSQL
SchemaFixed, predefinedFlexible / schema-less
ScalingVertical (mostly)Horizontal (built-in)
ConsistencyStrong (ACID)Often eventual (BASE)
JoinsYesNo (denormalize/embed)
QuerySQL (standard)Per-database APIs
Best forTransactions, complex queriesScale, flexible/large data
💡 Rule of thumb: choose SQL when you need transactions, joins, and strong consistency on structured data; choose NoSQL when you need massive scale, flexible schemas, or a specific data shape (documents, wide rows, key-value). Many real systems use both.

ACID vs BASE

🛢️ Databases · Foundations · 5 min read

Two consistency philosophies. ACID (relational) prioritizes correctness; BASE (many NoSQL) prioritizes availability and scale.

ACIDBASE
Atomicity — all or nothingBAsically Available — responds always
Consistency — always valid stateSoft state — may change over time
Isolation — txns don't interfereEventual consistency — converges later
Durability — survives crashes
💡 ACID = "correct now" (banking, orders). BASE = "available & fast, correct soon" (feeds, catalogs, analytics at scale). The trade-off ties directly to the CAP theorem — you can't have perfect consistency and availability during a network partition.

CAP Theorem

🛢️ Databases · Foundations · ★ In-depth · 8 min read

A distributed database can guarantee at most two of: Consistency, Availability, Partition tolerance. Since network partitions are inevitable, the real choice under a partition is C vs A.

Consistency Availability Partition tol. CP AP CA (single node only)
ChoiceBehaviourDatabases
CPConsistent; may reject requests during partitionMongoDB (default), HBase
APAvailable; may return stale dataCassandra, DynamoDB (eventual)
CAOnly without partitionsSingle-node MySQL
💡 Maps directly to our four DBs: MySQL (single node, CA → CP when clustered), MongoDB (CP-leaning), Cassandra (AP, tunable), DynamoDB (AP with optional strong reads). Modern nuance: PACELC adds the latency-vs-consistency trade-off even without a partition.

Data Modeling Basics

🛢️ Databases · Foundations · 5 min read

Data modeling is deciding how to structure data for your access patterns. The approach flips between SQL and NoSQL.

SQL (model the data)NoSQL (model the queries)
Start fromEntities & relationshipsAccess patterns / queries
GoalNormalize (avoid redundancy)Denormalize (avoid joins)
RelationshipsForeign keys + joinsEmbed or duplicate data
💡 Crucial mindset shift: in SQL you normalize and join; in NoSQL you design tables around the queries you'll run and duplicate data to serve them. Modeling the wrong way (e.g. normalizing in Cassandra/DynamoDB) is a top cause of NoSQL pain.

Which Database to Use

🛢️ Databases · Choosing · ★ In-depth · 10 min read

The most important database skill: matching the engine to your workload. Here's a practical decision guide for our four databases.

Decision Flow — Visual

Need transactions/joinson structured data? MySQLYES → relational MongoDBflexible docs, nested data Cassandrahuge write volume, multi-DC DynamoDBserverless KV, AWS NO (NoSQL) → pick by data shape + scale + ops model

Pick By Need

  • MySQL — you need ACID transactions, joins, strong consistency, structured/relational data (orders, payments, users). Default for most apps.
  • MongoDB — flexible/evolving schemas, nested/hierarchical documents, fast iteration (catalogs, content, profiles).
  • Cassandra — write-heavy at massive scale, multi-datacenter, always-on availability, time-series/event data (sensor logs, messaging).
  • DynamoDB — serverless key-value/document at any scale, predictable single-digit-ms latency, deep AWS integration, minimal ops.
💡 Start with the simplest thing that works — usually a relational DB (MySQL/PostgreSQL). Reach for NoSQL when you hit a real scaling/flexibility wall and your access patterns fit a specific NoSQL model. "Resume-driven" NoSQL adoption is a classic mistake.

Comparison Matrix

🛢️ Databases · Choosing · ★ In-depth · 8 min read

A head-to-head of the four databases across the dimensions that matter most.

MySQLMongoDBCassandraDynamoDB
ModelRelationalDocumentWide-columnKey-value/doc
SchemaFixedFlexibleFlexible (per-table)Flexible
ScalingVertical + read replicasHorizontal (sharding)Horizontal (masterless)Horizontal (managed)
ConsistencyStrong (ACID)Strong (CP-leaning)Tunable (AP)Eventual + strong opt
TransactionsFull ACIDMulti-doc (4.0+)Limited (LWT)Limited (per-region)
QuerySQL (joins)Rich query + aggregationCQL (no joins)Key lookups (no joins)
WritesGoodGoodExcellent (write-optimized)Excellent
OpsSelf/managed (RDS)Self/AtlasHeavy self-managedFully serverless
Sweet spotOLTP, complex queriesFlexible app dataMassive writes, multi-DCServerless scale on AWS
💡 Quick mnemonic: MySQL = structure & transactions · MongoDB = flexible documents · Cassandra = write-at-scale & availability · DynamoDB = serverless, hands-off scale on AWS.

Polyglot Persistence

🛢️ Databases · Choosing · 4 min read

Polyglot persistence means using multiple databases in one system, each for what it does best — rather than forcing everything into one engine.

# a typical e-commerce stack MySQL/PostgreSQL → orders, payments (ACID transactions) MongoDB → product catalog (flexible attributes) Redis → sessions, cart, cache (sub-ms) Elasticsearch → product search Cassandra/Dynamo → activity logs, events (write-heavy)
💡 Trade-off: best-fit performance vs operational complexity (more systems to run, back up, and keep consistent). Start with one database; introduce another only when a clear need justifies the overhead.

MySQL Overview

🛢️ Databases · MySQL · 4 min read

MySQL is the world's most popular open-source relational database — tables, SQL, and ACID transactions (via InnoDB). The default choice for structured, transactional data.

  • Relational — data in tables linked by keys; queried with SQL.
  • ACID via InnoDB — reliable transactions, foreign keys, row-level locking.
  • Mature ecosystem — replication, tooling, cloud (RDS/Aurora), Spring Data JPA.
💡 MySQL has a full dedicated tutorial on this site — 100 topics covering joins, indexes, transactions, optimization, replication, sharding, and more. → Open the full MySQL tutorial

When to Use MySQL

🛢️ Databases · MySQL · 3 min read

✓ Use MySQL when

  • You need ACID transactions (payments, orders)
  • Data is structured & relational
  • You need complex queries & joins
  • Strong consistency matters
  • Team knows SQL (most do)

✗ Consider alternatives when

  • Schema changes constantly → MongoDB
  • Write volume exceeds one server → Cassandra
  • You want zero DB ops on AWS → DynamoDB
  • Data is graph/search/time-series shaped
💡 MySQL (or PostgreSQL) is the right default for ~80% of applications. Only move to NoSQL when you have a concrete reason the relational model can't serve.

Introduction to MongoDB

🍃 Databases · MongoDB · ★ In-depth · 8 min read

MongoDB is the leading document database. It stores data as flexible, JSON-like documents (BSON) instead of rows in tables — so a record and its nested data live together, with no fixed schema.

Relational vs Document — Visual

Relational (3 tables + joins) users orders addresses Document (one document) { _id, name: "Aftab", addresses: [ {...}, {...} ], orders: [ { id, total, items: [...] } ] } all related data in one place — no join

Why MongoDB

  • Flexible schema — documents in a collection can differ; evolve without migrations.
  • Natural for objects — maps directly to app objects/JSON (no ORM impedance mismatch).
  • Horizontal scale — built-in sharding & replica sets.
  • Rich queries — secondary indexes, aggregation pipeline, geospatial, text search.
💡 Mental map: database → collection → document → field (vs SQL's database → table → row → column). A document is a JSON object with nested arrays/objects — embed related data to avoid joins.

Documents & Collections

🍃 Databases · MongoDB · 4 min read

A document is a BSON (binary JSON) object; a collection is a group of documents (like a table without a fixed schema).

{ "_id": ObjectId("65a1..."), // auto primary key "name": "Aftab", "email": "a@x.com", "tags": ["admin", "vip"], // arrays "address": { "city": "Noida", "zip": "201301" } // nested object }
SQLMongoDB
DatabaseDatabase
TableCollection
RowDocument
ColumnField
💡 Every document has a unique _id (auto-generated ObjectId if you don't supply one). BSON adds types JSON lacks — dates, ObjectId, binary, decimal.

CRUD Operations

🍃 Databases · MongoDB · 5 min read
// CREATE db.users.insertOne({ name: "Sam", age: 30 }); db.users.insertMany([{...}, {...}]); // READ db.users.find({ age: { $gt: 25 } }); db.users.findOne({ email: "a@x.com" }); // UPDATE db.users.updateOne({ _id: id }, { $set: { age: 31 } }); db.users.updateMany({ active: false }, { $set: { status: "archived" } }); // DELETE db.users.deleteOne({ _id: id }); db.users.deleteMany({ status: "archived" });
💡 Update operators ($set, $inc, $push, $pull) modify specific fields without rewriting the whole document. upsert: true inserts if no match is found.

Query Operators

🍃 Databases · MongoDB · 4 min read
// comparison db.products.find({ price: { $gte: 100, $lte: 500 } }); db.products.find({ category: { $in: ["a", "b"] } }); // logical db.users.find({ $or: [{ age: { $lt: 18 } }, { vip: true }] }); // arrays & nested db.users.find({ tags: "admin" }); // array contains db.users.find({ "address.city": "Noida" }); // dot notation // projection, sort, paginate db.users.find({}, { name: 1, _id: 0 }).sort({ age: -1 }).skip(20).limit(10);
CategoryOperators
Comparison$eq $ne $gt $gte $lt $lte $in $nin
Logical$and $or $not $nor
Element/Array$exists $type $all $elemMatch $size
💡 Dot notation queries nested fields/arrays. Use projection ({ field: 1 }) to fetch only needed fields — like avoiding SELECT *.

Indexing

🍃 Databases · MongoDB · 4 min read

Indexes (B-tree) speed up queries — same principle as SQL. Without one, MongoDB does a full collection scan.

db.users.createIndex({ email: 1 }, { unique: true }); // single, unique db.orders.createIndex({ userId: 1, createdAt: -1 }); // compound db.products.createIndex({ name: "text" }); // text search db.places.createIndex({ location: "2dsphere" }); // geospatial db.users.find({ email: "a@x.com" }).explain("executionStats");
💡 Index types: single, compound (left-prefix rule like SQL), multikey (arrays), text, geospatial, TTL (auto-expire docs). Index your query/sort fields; use explain() to verify usage. Over-indexing slows writes.

Aggregation Pipeline

🍃 Databases · MongoDB · ★ In-depth · 8 min read

The aggregation pipeline processes documents through a sequence of stages, each transforming the stream — MongoDB's equivalent of SQL GROUP BY + analytics, but far more powerful.

Pipeline Flow — Visual

$matchfilter (like WHERE) $groupaggregate (GROUP BY) $sortorder $projectreshape result
db.orders.aggregate([ { $match: { status: "paid" } }, // filter { $group: { _id: "$userId", total: { $sum: "$amount" }, n: { $sum: 1 } } }, { $sort: { total: -1 } }, // sort { $limit: 10 }, { $project: { userId: "$_id", total: 1, _id: 0 } } // reshape ]);
StageDoes (SQL analogue)
$matchFilter (WHERE)
$groupAggregate (GROUP BY + aggregates)
$sort / $limitORDER BY / LIMIT
$projectSelect/reshape columns
$lookupLeft join to another collection
$unwindFlatten an array into rows
💡 Put $match (and $sort on indexed fields) early so the pipeline uses indexes and processes fewer documents. $lookup gives you joins when you really need them — but heavy use suggests the data should have been embedded.

Schema Design (Embedding vs Referencing)

🍃 Databases · MongoDB · ★ In-depth · 8 min read

The central MongoDB design decision: embed related data inside a document, or reference it in another collection. Get this right and MongoDB flies; get it wrong and you fight the database.

Embed vs Reference — Visual

Embed (1:few, read together) { _id, name, addresses: [ { city, zip }, { city, zip } ] } one read, no join · atomic update Reference (1:many, large/shared) user { _id, name }orders collection → order { userId } link by id · needs extra query / $lookup

Which to Choose

Embed when…Reference when…
Data is read togetherData is large or accessed independently
1-to-few relationship1-to-many / many-to-many (unbounded)
Child has no life of its ownChild is shared across parents
You want atomic updatesDocument would grow without bound
💡 Golden rule: "data that is accessed together should be stored together." Favour embedding (MongoDB's superpower — one read, no joins); reference only for large, shared, or unbounded relationships. Watch the 16 MB document size limit. Model around your read patterns, not entities.

Replica Sets

🍃 Databases · MongoDB · 4 min read

A replica set is a group of MongoDB nodes holding the same data — one primary (writes) and several secondaries (replicate & serve reads). Provides high availability and read scaling.

Primary (writes) Secondary Secondary replicate oplog
💡 If the primary fails, the set holds an automatic election and a secondary is promoted (typically <15s) — that's the high-availability guarantee. Reads can be routed to secondaries (with read-preference), accepting slight replication lag.

Sharding

🍃 Databases · MongoDB · 4 min read

Sharding partitions a collection across multiple machines (shards) by a shard key — enabling horizontal scale beyond one server for huge datasets/throughput.

  • Shard key — determines how documents distribute; choose one with high cardinality and even access (avoid hotspots).
  • mongos router — routes queries to the right shard(s).
  • Config servers — store cluster metadata.
  • Each shard is itself a replica set (HA + scale).
⚠️ Shard key choice is critical and hard to change later. A poor key (low cardinality or monotonic, like a timestamp) creates hotspots where all writes hit one shard. Only shard when a single replica set can't cope.

Transactions

🍃 Databases · MongoDB · 4 min read

Since v4.0, MongoDB supports multi-document ACID transactions — though for many apps a well-embedded document makes them unnecessary (single-document writes are already atomic).

const session = client.startSession(); session.startTransaction(); try { await accounts.updateOne({ _id: a }, { $inc: { bal: -100 } }, { session }); await accounts.updateOne({ _id: b }, { $inc: { bal: 100 } }, { session }); await session.commitTransaction(); } catch (e) { await session.abortTransaction(); }
💡 Single-document operations are always atomic — if you embed related data well, you rarely need multi-document transactions. Use them for true cross-document invariants (e.g. money transfer across accounts). They carry more overhead than single-doc writes.

When to Use MongoDB

🍃 Databases · MongoDB · 3 min read

✓ Use MongoDB when

  • Schema evolves rapidly / varies per record
  • Data is hierarchical / nested (documents)
  • You want fast iteration without migrations
  • Read patterns fit "fetch one rich document"
  • You need easy horizontal scaling

✗ Avoid when

  • Heavy multi-entity transactions & joins → MySQL
  • Highly relational data with many links
  • You need strict, enforced schema constraints
  • Extreme write scale across DCs → Cassandra
💡 Great for catalogs, content/CMS, user profiles, event/IoT payloads, real-time apps. The flexible document model shines when data is naturally hierarchical and read together.

Introduction to Cassandra

🟣 Databases · Cassandra · 4 min read

Apache Cassandra is a distributed wide-column NoSQL database built for massive write throughput, linear horizontal scale, and no single point of failure. Originally from Facebook; now widely used at internet scale (Netflix, Apple, Discord).

  • Masterless — every node is equal (peer-to-peer ring); no primary bottleneck.
  • Always-on — survives node/datacenter failures; multi-DC native.
  • Write-optimized — extremely fast writes (append-only log + memtable).
  • AP (CAP) with tunable consistency per query.
💡 Cassandra trades joins, ad-hoc queries, and strong consistency for scale and availability. You model tables around queries and accept eventual consistency — the opposite mindset to MySQL.

Cassandra Architecture

🟣 Databases · Cassandra · ★ In-depth · 7 min read

Cassandra runs as a masterless ring of equal nodes. Data is distributed by hashing the partition key; each node owns a range of the hash space. Any node can serve any request (acting as coordinator).

N1 N2 N3 N4 ring no master
  • Partitioner hashes the partition key → places data on a node (and its replicas).
  • Replication factor (RF) — how many nodes hold each row's copy.
  • Gossip protocol — nodes share state; no leader election needed.
  • Storage: commit log → memtable → SSTables (append-only; compaction merges them).
💡 The masterless ring is why Cassandra scales linearly (add nodes = add capacity) and has no single point of failure. The write path (append to commit log + memtable) is why writes are blazing fast.

Wide-Column Data Model

🟣 Databases · Cassandra · 4 min read

Data lives in tables grouped into keyspaces. Rows are grouped into partitions; within a partition, rows can have many columns. You design one table per query — denormalization and duplication are normal.

CassandraRoughly like
KeyspaceDatabase (sets replication)
TableTable (but query-specific)
PartitionGroup of rows on one node
Row / ColumnRow / Column
💡 Cardinal rule: "one table per query." No joins exist — you duplicate data into multiple tables, each shaped for a specific read. Modeling like a relational DB (then trying to join) is the #1 Cassandra mistake.

Partition & Clustering Keys

🟣 Databases · Cassandra · ★ In-depth · 7 min read

The primary key drives everything in Cassandra — data placement and sort order. It splits into a partition key (which node) and optional clustering columns (sort within the partition).

CREATE TABLE messages ( room_id uuid, -- partition key → which node sent_at timestamp, -- clustering key → sort within partition msg_id uuid, body text, PRIMARY KEY ((room_id), sent_at, msg_id) ) WITH CLUSTERING ORDER BY (sent_at DESC);
Partition keyhash → node placement Clustering columnssort order within partition = PRIMARY KEY
⚠️ You can only filter efficiently on the partition key (+ clustering columns in order). No arbitrary WHERE/joins. Avoid large partitions (unbounded growth) and hot partitions (all traffic to one key). Design the key from your query — this decision is the whole game.

CQL (Cassandra Query Language)

🟣 Databases · Cassandra · 3 min read

CQL looks like SQL but is intentionally limited — no joins, no arbitrary WHERE, no aggregation across partitions.

INSERT INTO messages (room_id, sent_at, msg_id, body) VALUES (?, ?, ?, ?); SELECT * FROM messages WHERE room_id = ? AND sent_at > ?; -- must hit partition key UPDATE messages SET body = ? WHERE room_id = ? AND sent_at = ? AND msg_id = ?;
⚠️ SQL-like syntax hides very different rules: queries must include the partition key, you can't JOIN or GROUP BY across partitions, and ALLOW FILTERING (full scan) is a red flag in production. Model tables so every query targets one partition.

Tunable Consistency

🟣 Databases · Cassandra · 4 min read

Cassandra lets you choose the consistency level per query — how many replicas must respond before success. You tune the consistency/availability/latency trade-off.

LevelMeaning
ONE1 replica responds (fast, weak)
QUORUMMajority of replicas (balanced)
LOCAL_QUORUMMajority in the local DC (common)
ALLEvery replica (strong, slow)
💡 Strong consistency rule: R + W > RF (read + write replicas exceed replication factor). E.g. RF=3 with QUORUM reads & writes (2+2>3) gives strong consistency while tolerating one node down. LOCAL_QUORUM is the typical multi-DC default.

Replication

🟣 Databases · Cassandra · 3 min read

Each keyspace sets a replication factor (RF) — how many copies of each row exist across the ring — and a strategy for placing them (often per datacenter).

CREATE KEYSPACE app WITH replication = { 'class': 'NetworkTopologyStrategy', 'dc1': 3, 'dc2': 3 -- 3 copies in each datacenter };
💡 RF=3 is typical — survive losing 2 replicas. NetworkTopologyStrategy spreads replicas across datacenters for multi-region resilience. Replication + tunable consistency together deliver "always-on" with controllable correctness.

When to Use Cassandra

🟣 Databases · Cassandra · 3 min read

✓ Use Cassandra when

  • Write volume is huge & constant
  • You need linear horizontal scale
  • Always-on / multi-datacenter availability
  • Time-series, logs, events, messaging, IoT
  • Access patterns are known & query-shaped

✗ Avoid when

  • You need joins / ad-hoc queries → MySQL
  • Strong transactions across rows
  • Access patterns are unknown/changing
  • Small data or a small team (ops-heavy)
💡 Cassandra is a specialist: pick it for write-heavy, always-on, scale-out workloads with well-defined queries. It's operationally heavy — don't reach for it unless you genuinely need that scale/availability (managed options: DataStax Astra, Amazon Keyspaces).

Introduction to DynamoDB

🟠 Databases · DynamoDB · 4 min read

Amazon DynamoDB is a fully managed, serverless key-value & document NoSQL database. It delivers single-digit-millisecond latency at any scale with zero servers to manage — you just create tables and AWS handles everything else.

  • Serverless — no provisioning, patching, or scaling ops; pay per use.
  • Predictable performance — consistent low latency regardless of size.
  • Scales automatically — from a few requests to millions/sec.
  • AWS-native — IAM, Lambda, Streams, global tables.
💡 DynamoDB is the go-to for serverless/AWS apps needing massive scale with no DB administration. Like Cassandra, you design around access patterns — but AWS runs the cluster for you.

Partition & Sort Keys

🟠 Databases · DynamoDB · ★ In-depth · 7 min read

Every DynamoDB item is located by its primary key: a partition key (which physical partition) and an optional sort key (order within that partition). Key design is the data model.

Partition Key (PK)hashed → partition Sort Key (SK)range within partition = unique item
Key typeUse
Partition key onlySimple key-value lookup (one item per key)
Partition + Sort keyMany items per partition, queryable by range/prefix
# query all orders for a user, newest first PK = "USER#42", SK begins_with "ORDER#" → Query (fast) # Query needs the partition key; Scan reads the whole table (avoid)
⚠️ You can only Query within a partition key (+ sort key conditions). A full-table Scan is slow and costly. Choose a high-cardinality, evenly-accessed partition key to avoid "hot partitions". This mirrors Cassandra's partition/clustering keys.

Capacity Modes

🟠 Databases · DynamoDB · 3 min read

DynamoDB bills throughput in two modes:

ModeHow it worksBest for
On-DemandPay per request; auto-scales instantlySpiky/unknown traffic, simplicity
ProvisionedSet RCU/WCU (+ auto-scaling)Predictable traffic, lowest cost
💡 Start with On-Demand (no capacity planning); switch to Provisioned + auto-scaling once traffic is predictable and you want to optimize cost. RCU = read capacity unit, WCU = write capacity unit.

Secondary Indexes (GSI & LSI)

🟠 Databases · DynamoDB · 4 min read

Secondary indexes let you query by attributes other than the primary key — essential since base-table queries are limited to the key.

GSI (Global)LSI (Local)
Partition keyDifferent from base tableSame as base table
CreatedAnytimeOnly at table creation
ConsistencyEventual onlyStrong possible
UseQuery by any attributeAlternate sort key
💡 GSIs are how you support multiple access patterns on one table (e.g. query orders by status, or by date). They're the workhorse for DynamoDB query flexibility — each is essentially a re-projected copy of the data with its own keys.

Single-Table Design

🟠 Databases · DynamoDB · ★ In-depth · 7 min read

DynamoDB's signature (and counter-intuitive) pattern: store multiple entity types in one table, using generic key names and key prefixes — so related items share a partition and one query fetches them together (since there are no joins).

PK | SK USER#42 | PROFILE USER#42 | ORDER#1001 USER#42 | ORDER#1002 USER#42 | ADDRESS#home One Query onPK=USER#42 returns the user +all orders + address → no joins, one round-trip
💡 Different entities (profile, orders, addresses) live under one partition key so a single Query returns them together — emulating a join. It's powerful but advanced; it requires knowing all access patterns up front. For simpler apps, multiple tables are perfectly fine and easier to reason about.

DynamoDB Streams

🟠 Databases · DynamoDB · 3 min read

Streams capture an ordered log of item-level changes (insert/modify/delete), which a Lambda can consume in near-real-time — enabling event-driven architectures.

Table change → DynamoDB Stream → Lambda trigger → { update search index · send notification · replicate · aggregate analytics }
💡 Streams power CDC (change data capture), cross-region replication (Global Tables use them), materialized views, and event-driven workflows — the serverless equivalent of database triggers, decoupled via Lambda.

Consistency

🟠 Databases · DynamoDB · 3 min read

DynamoDB offers two read consistency models per request:

ModelBehaviourCost
Eventually consistent (default)May briefly return stale dataCheaper, faster
Strongly consistentAlways latest committed value2× read cost, same region
💡 Default reads are eventually consistent (AP-style). Request strong consistency when you must read your own writes immediately. Also supports ACID transactions (TransactWriteItems) for multi-item atomic operations within a region.

When to Use DynamoDB

🟠 Databases · DynamoDB · 3 min read

✓ Use DynamoDB when

  • You're on AWS & want zero DB ops
  • Serverless apps (Lambda) needing scale
  • Predictable single-digit-ms latency at scale
  • Key-value / known access patterns
  • Spiky traffic (on-demand auto-scales)

✗ Avoid when

  • You need joins / complex ad-hoc queries → MySQL
  • Access patterns are unknown / will change a lot
  • Not on AWS (it's AWS-only)
  • Rich analytics / reporting (use a warehouse)
💡 DynamoDB shines for serverless AWS workloads at scale with known access patterns and minimal ops. The trade-off vs Cassandra: DynamoDB is fully managed but AWS-locked; Cassandra is open-source/portable but you run it. Both demand query-first data modeling.