Concept lesson · Foundations
Databases, data models, and ACID transactions
Start here
Definition
A database is an organized collection of related data; a database management system (DBMS) is the software that stores, retrieves and updates it. A data model defines how the data is represented and related. A transaction treats one or more operations as a single logical unit: its changes commit together or are rolled back together. ACID names atomicity, ACID consistency, isolation and durability; the database and its settings determine the precise concurrency and failure guarantees.
Why it matters: A product needs to answer specific queries and keep shared facts correct when requests overlap or fail. The database choice must support both the access patterns and the required transaction boundary.
Choose records by the query, then use an atomic transaction for the inventory/order relationship.
Read the diagram step by step
- A relational row supports constraints and joins; a document groups an aggregate; a key-value record addresses one known key; graph edges support traversal.
- Model choice does not by itself make a purchase safe.
- For two mugs with stock five, decrement stock and insert the order atomically. Either both changes commit or neither does.
Worked example
Buying two mugs must change stock from 5 to 3 and create order O81 for $24. A local transaction can commit both changes or neither; if the two changes are saved independently, a crash between them can leave stock reduced without a matching order.
Key takeaways
- Start with access patterns and invariants before choosing a database family.
- ACID names four distinct guarantees; its C differs from CAP consistency.
- Relational and NoSQL are not synonyms for strong and weak consistency.
You will learn to
- Compare relational, key-value, document, wide-column, and graph records.
- Connect schema, query, scaling, and transaction needs to a storage choice.
- Explain ACID using a purchase that changes inventory and order state.
Practice in this chapter
8 interview questions with model answers and follow-ups.
Go to interview practiceUseful foundations: Database indexes: B-trees, composite keys and query access
Workload and timing examples are interview assumptions.
Dotted concept links open the relevant explanation in a new tab.
01What is a database, data model, and transaction?
A database is an organized collection of related data. A database management system (DBMS) is the software that stores, retrieves and updates it. In everyday engineering conversation, “database” often refers to the combined system. Its data model determines whether the application thinks in tables, documents, key-value pairs, or relationships. An access pattern is a concrete query or update, such as “find recent orders for customer U7.” An invariant is a rule that must remain true, such as “available stock never becomes negative.”
A transaction groups database operations so their changes commit together or roll back together. ACID names four properties: atomicity, ACID consistency, isolation and durability. They describe what commits together, which rules remain valid, how concurrent transactions interact and which failures saved data survives. Check the database’s guarantees against your reads and writes.
One database is a sensible starting point. As the service grows, its limit might be storage, popular-item contention, history reads, or expensive analytics. The label SQL or NoSQL does not identify which limit we have. First write the questions and rules; then choose a model and implementation that support them.
Assume this purchase must create the order and allocate stock together or do neither. We have not yet introduced independent payment and warehouse services. Keeping inventory and orders in one database lets us explain a local transaction before considering a workflow that spans separate services. The quantities and prices are assumptions for this example.
Derive the model from the required operations: conditional stock allocation, order lookup by ID, and customer history ordered by time. In the example, order O81 contains two MUG9 items at an assumed $12 each. Creating the $24 order changes available stock from five to three. That joint state transition defines the required transaction boundary.
02Relational data: tables, keys, joins, and constraints
A relational database represents facts as rows in tables. Columns name fields and usually assign their types. Relationships connect records through keys. Separate shared inventory from each order’s agreed commercial terms.
Arrows point from foreign keys to the records they reference. This is a simplified key relationship diagram; an order line also needs its own unique identity in the real schema.
Remember: Primary key identifies; foreign key references; constraints protect rules.
Read the diagram
- 1. Customer row: customerId is the primary key: one customer identity.
- 2. Order row: orderId is its primary key; customerId refers to the customer.
- 3. Order-line rows: Each line refers to orderId and a product; it stores agreed price and quantity.
- 4. Constraints: Foreign keys and checks reject selected invalid states at the database boundary.
| Table | Example record | Important question |
|---|---|---|
| Customer | U7 | Who owns the order? |
| Inventory | MUG9, available = 5 | Can two units be allocated? |
| Orders | O81, customer U7, total 24 | What is its current state? |
| OrderLine | O81, MUG9, quantity 2, unitPrice 12 | Which quantity and price were committed? |
OrderLine retains the purchase price if tomorrow’s catalog price changes. This deliberate duplication preserves history; eliminating every repeated field is not the goal.
SQL is a language for querying and changing relational data. A join combines O81 with its lines. An index beginning with customer and then creation order supports customer U7’s order history. Constraints such as a unique order identifier or a valid customer reference enforce specific rules within the database’s supported scope.
A useful history index is (customer_id, created_at DESC, order_id DESC), supporting a query shaped like SELECT ... FROM Orders WHERE customer_id = 'U7' ORDER BY created_at DESC, order_id DESC LIMIT 20. The final key breaks equal-time ties. It does not make an unrelated full-catalog search cheap. Store money as integer minor units or an exact decimal plus currency; the illustrative $12 unit price can be 1200 cents, and two units total 2400 cents.
03Key-value, document, wide-column, and graph models
The order, its line items and the customer relationship can be represented in several models. The choice changes which related facts are stored together and which queries need additional lookups or indexes. Compare each alternative against the same two needs: fetch O81 as a complete order and list U7’s recent orders.
A key-value store retrieves a value by a key, such as order:O81 → complete order data. That fits exact lookup. Listing every order for U7 needs another supported access path; one key does not automatically answer every question.
A document store can keep the order and its lines together: {id: O81, customer: U7, lines: [{sku: MUG9, qty: 2, price: 12}]}. This makes a complete-order read natural. Shared inventory remains separate because many orders refer to MUG9. Convenient embedding does not automatically make that cross-document rule atomic.
| Family | Representation | Natural access |
|---|---|---|
| Key-value | order:O81 → order payload | Fetch O81 |
| Document | Order with embedded lines | Read the whole order aggregate |
| Wide-column | Partition U7; keys ordered by time and order ID | Read U7’s recent orders |
| Graph | U7 → placed → O81 → contains → MUG9 | Traverse relationships |
Wide-column systems organize application queries around partition keys, which select a group of records, and clustering keys, which order records within that group. They differ from analytical columnar engines that scan selected columns over many rows. Graph storage is useful when traversals are central, not merely because two records are related.
Choose by both fit and the operation that becomes awkward. A key-value layout needs a separate access path for customer history. A document layout makes one bounded order aggregate easy, but very large embedded arrays and shared inventory need another strategy. A wide-column layout favors planned partition-key queries and can concentrate a very large customer partition. A graph model makes multi-hop traversal expressive, but a relational foreign key alone does not justify adding a graph engine.
- 1 → 2validate and deduplicatePurchase: 2 × MUG9 → Purchase transaction
- 2 → 3conditional allocationPurchase transaction → Inventory: 5 → 3
- 2 → 4create matching orderPurchase transaction → Order O81: $24
- 2 → 5reply after commitPurchase transaction → Committed purchase response
- 4 → 6publish committed changesOrder O81: $24 → Derived read views
04SQL versus NoSQL: choose from workload and constraints
Schema is the agreed structure and meaning of records. A relational schema can enforce types and constraints. A flexible document schema can permit different shapes, but the application still needs rules for quantity, currency, and missing fields. Either model needs a compatible plan when old and new software versions coexist.
NoSQL describes a broad family, not one query language or consistency setting. Different systems expose document queries, keyed operations, graph languages, or SQL-like syntax. Some support multi-record transactions; MongoDB documents transaction support.
For this purchase, choose a relational database with appropriate transaction support. The reasons are the shared stock/order rule and useful history queries. We pay for indexes, contention on a hot product, and operating the database. We are not assuming that relational databases cannot distribute or that document stores cannot transact. If search or analytics requires another engine, treat it as a derived view of committed orders with a stated freshness delay and rebuild path.
05ACID: atomicity, consistency, isolation, durability
A transaction groups changes under specified guarantees. For O81, begin the transaction, reduce MUG9 stock by two only if at least two remain, insert the matching order and line, then commit. If a required step fails, roll back the transaction.
| Letter | Meaning for O81 |
|---|---|
| Atomicity | Stock and order commit together or neither does |
| C: ACID consistency | A correct transaction takes the database from one valid state to another, preserving rules such as nonnegative stock |
| Isolation | Limits which intermediate or concurrent changes a purchase transaction can observe; the selected isolation level determines the exact guarantees |
| Durability | Committed O81 survives the failures covered by storage/replication settings |
Keep the meanings separate
Rules involving several records may require stronger isolation or explicit locking. “ACID” does not mean every default isolation mode prevents every anomaly. The transactions-and-isolation chapter develops those traces; PostgreSQL’s isolation reference describes actual engine behavior. Application logic must still express the right invariant.
The transaction also records which logical purchase it is performing. purchase_key stays the same across retries; request_hash summarizes a consistently normalized request so the same key cannot silently mean different quantities or items. A row lock prevents competing updates to the same inventory row from proceeding simultaneously. That protection lets the database wait for an earlier updater and then test whether stock is still sufficient.
Here is the key part of a PostgreSQL-style transaction, assuming the tables and their uniqueness/foreign-key constraints already exist:
BEGIN;
INSERT INTO Orders
(order_id, customer_id, purchase_key, request_hash, total_cents, currency)
VALUES ('O81', 'U7', 'purchase-71', 'hash-of-canonical-request', 2400, 'USD');
UPDATE Inventory
SET available = available - 2
WHERE sku = 'MUG9' AND available >= 2
RETURNING available;
-- Continue only if exactly one row was returned; otherwise ROLLBACK.
INSERT INTO OrderLine
(order_id, sku, quantity, unit_price_cents)
VALUES ('O81', 'MUG9', 2, 1200);
COMMIT;
The comment is an application decision, not SQL that automatically aborts. Also enforce UNIQUE(customer_id, purchase_key) and a nonnegative-stock constraint. At PostgreSQL Read Committed, a competing updater waits for the row lock and rechecks its predicate against the updated row. Starting from two units, T1 changes 2 → 0 and commits; T2 then finds available >= 2 false and must roll back its transaction, removing the order it inserted earlier in that attempt. Starting from five, the single purchase changes 5 → 3. More complex multi-row rules still need the stronger strategy described above.
Claim the unique purchase key before allocating stock, as in this SQL order. A duplicate waits for the first transaction and recovers its existing outcome even if the successful purchase exhausted inventory. The new order remains uncommitted until all steps succeed; an insufficient-stock rollback removes it too. Performing the stock check first without resolving a prior purchase could incorrectly return out-of-stock for a retry of an already successful order.
06Unknown commits and changing transaction boundaries
Large images belong in storage suited to media bytes and delivery, with authoritative metadata references. Analytics can scan a derived store so monthly reports do not crowd out purchases. Add those paths when requirements and measurements justify their maintenance cost. Each derived view needs committed input, a freshness policy, and a recovery mechanism.
Two concurrency failures also require a fresh attempt. A serialization failure means the database cannot safely commit the attempted concurrent execution under its isolation rules. A deadlock occurs when transactions wait on one another’s held resources in a cycle; the database aborts an attempt to break that cycle. In either case, the application must reevaluate the purchase from fresh reads.
If the purchase key already exists, roll back the whole attempt. Then read the earlier order and its request hash in a new transaction. In this example, the duplicate is detected before stock is allocated. Return the saved result only if the normalized request matches. After a serialization failure or deadlock, retry the whole transaction with the same purchase ID and a retry limit, not just the final INSERT.
07Interview answer: choose a database for orders
Interviewer: “Would you use SQL or NoSQL for orders?”
Candidate: “I would list the queries and atomic rules first. The workload needs O81 by ID, recent orders for U7, and a purchase changing shared inventory from five to three while creating the matching order. A relational model with indexes and a suitable transaction is a straightforward starting point.
“A document can make complete-order reads convenient, but inventory is shared across many orders. I still need a supported transaction, or an explicit stock-reservation workflow, to coordinate that change with order creation. I would not claim one family always scales better or always lacks transactions. If history reads dominate later, I can add a read model. If inventory becomes an independent service, I must redesign the workflow.”
The answer connects a storage choice to the work the product performs and names what would make us reconsider. That is more useful than choosing from vendor slogans or treating a flexible schema as permission to skip data modeling.
Practise the interview questions
Say your answer aloud before opening the model answer. Then answer the follow-up and compare the reasoning.
What are a data model, access pattern, invariant, and transaction? How do they guide database choice?
Reveal a model answer
A data model describes the representation: tables, documents, key-value pairs, or graph relationships. An access pattern is a specific query or update, such as recent orders for customer U7. An invariant is a rule that must remain true, such as stock never becoming negative. A transaction treats operations as one logical unit whose changes commit or roll back together. ACID names atomicity, ACID consistency, isolation and durability; the engine and its settings determine the exact guarantees.
For an order service, write down order-by-ID, customer history, and conditional stock allocation. If reducing stock from 5 to 3 must commit with creating a $24 order, a relational database with suitable indexes and a local transaction is a straightforward starting point. Then test expected volume, hot-item contention, and the actual engine's features. SQL and NoSQL labels alone do not determine scale or transaction support.
Interviewer follow-up
Would a billion rows automatically change your choice?
Reveal the follow-up answer
“No. Row size, access locality, indexes, request rate, and partitioning capabilities determine the bottleneck. I would identify the limiting operation first.”
What the answer must demonstrate: Size alone does not describe a workload.
An order contains its item lines, while product inventory is shared across many orders. Would storing each order as one document make the whole purchase atomic?
Reveal a model answer
“Embedding O81’s lines makes the order read convenient, but MUG9 stock is shared by many orders. Copying available quantity into each order creates competing truths. I would keep stock in one authoritative inventory system and use a supported transaction, or an explicit reservation workflow, to coordinate stock allocation with the order.”
Interviewer follow-up
When is embedding a good idea?
Reveal the follow-up answer
“When related data is normally read or updated together and remains bounded. It simplifies that aggregate without removing relationships outside it.”
What the answer must demonstrate: Distinguish one aggregate from all shared state.
How does wide-column differ from analytical columnar storage?
Reveal a model answer
“A wide-column model can place U7’s orders in one partition and order them by time for a known serving query. Analytical columnar storage supports scans of selected attributes across many records. Similar names do not make their access shapes or guarantees interchangeable.”
Interviewer follow-up
Where would a monthly aggregate report run?
Reveal the follow-up answer
“I would consider a derived analytical path if scans disrupt purchases, then define its lag and reconciliation. A serving database and report workload need not share one bottleneck.”
What the answer must demonstrate: Avoid treating column-related names as one category.
A purchase must create order O81 for two $12 items and reduce stock from 5 to 3. Explain ACID for that transaction.
Reveal a model answer
“Atomicity makes stock allocation and order insertion succeed together or have neither change take effect. Correct logic preserves nonnegative stock. Isolation governs concurrent buyers. Durability defines which failures committed O81 survives. I would show the transaction and its settings because saying ‘ACID database’ does not prove the application rule.”
Interviewer follow-up
Is ACID consistency the same as CAP consistency?
Reveal the follow-up answer
No. ACID consistency preserves database and application rules, such as nonnegative stock. CAP consistency means linearizability: after a write completes, a later read must see it or a newer write. A store can serve fresh values while bad transaction logic breaks a business rule.
What the answer must demonstrate: Name the rule and distinguish the two meanings.
Two concurrent purchases each request two units when stock is two. What prevents overselling?
Reveal a model answer
“I put UPDATE Inventory SET available = available - 2 WHERE sku = the_requested_sku AND available >= 2 in the same transaction as the order insertion, and require one affected row before continuing. In PostgreSQL Read Committed, the second updater waits and rechecks the predicate. If the first commits stock 2 → 0, the second affects zero rows and rolls back instead of creating an order. A stock CHECK constraint is useful defense, but I still need the transaction and affected-row check.”
Interviewer follow-up
What if the rule spans several products?
Reveal the follow-up answer
“I need a transaction strategy protecting the whole rule or a deliberate reservation workflow. One row’s condition cannot enforce an unstated cross-row invariant.”
What the answer must demonstrate: A fresh read is not an atomic allocation.
Why does a flexible schema still need planning?
Reveal a model answer
“Old and new consumers must agree on quantity, currency, and record versions. Permitting multiple shapes does not tell the application how to interpret them. I would validate required fields and stage compatible readers and writers so a storage change does not silently change meaning.”
Interviewer follow-up
Must a relational schema alteration require downtime?
Reveal the follow-up answer
“Not universally. The exact operation and engine determine locks and rewrite costs; many changes can be staged compatibly.”
What the answer must demonstrate: Flexibility does not eliminate migration work.
Order O81 commits but the response is lost. How should the application recover the outcome?
Reveal a model answer
“The retry carries the same customer-scoped purchase key and request. I claim that unique key when inserting the uncommitted order, before allocating stock. If the key conflicts, I roll back the attempt, then use a fresh transaction to read and validate the original order’s request hash. This returns the original success even if it exhausted the remaining stock. A new purchase ID or a stock check performed before resolving the duplicate would give the wrong retry behavior.”
Interviewer follow-up
What if the retry changes the quantity?
Reveal the follow-up answer
“I reject reuse of the same identifier for different request data, or apply an explicit documented policy. It cannot silently mean another purchase.”
What the answer must demonstrate: Unknown commit is different from known rollback.
What changes when inventory becomes an independent service?
Reveal a model answer
“The stock and order updates no longer share the original local transaction. I must choose a distributed transaction or durable reservation workflow with explicit intermediate and compensation states. Moving tables across owners without revisiting that boundary loses the guarantee my first design depended on.”
Interviewer follow-up
Could a search index become the stock authority?
Reveal the follow-up answer
“No. Search is a derived discovery path and may lag. A purchase still requires the system that enforces the stock rule.”
What the answer must demonstrate: Ownership changes can change correctness, not only performance.
Blank-page exercise · 15 minutes
Build the answer yourself
Model order O81 for two MUG9 items at $12 each using relational tables and an embedded document. Specify indexes and the transaction that creates the $24 order while changing stock from 5 to 3.
- Show keys for order lookup and customer history.
- Distinguish shared inventory from the immutable purchase-price snapshot.
- Trace two competing buyers through conditional allocation.
- Recover an order whose commit response was lost.
Check that each component and design decision follows from your requirements and workload.
Recall the key ideas
Answer from memory before opening each card. Explain why the choice works and what it costs. Revisit missed cards tomorrow.
Databases, data models, and ACID transactionsWhat comes before SQL versus NoSQL?Recall first, then reveal
The important read/write patterns and the rules that must hold together.
Questions first, product second.
Return to lessonDatabases, data models, and ACID transactionsHow does one purchase explain ACID?Recall first, then reveal
Stock allocation and order creation commit together, preserve rules under the chosen concurrency model, and survive the configured failures.
One purchase, one protected decision.
Return to lessonDatabases, data models, and ACID transactionsDoes flexible schema mean no schema?Recall first, then reveal
Applications still need field meanings, validation, and version compatibility.
Flexible shape still needs shared meaning.
Return to lessonDatabases, data models, and ACID transactionsWhy keep the purchase price in OrderLine?Recall first, then reveal
It records the price committed at purchase time, independently of later catalog changes.
History is a fact, not a live catalog lookup.
Return to lessonFinal revision
Summary and interview notes
Choose a database from the reads, writes and rules your service needs. Show how concurrent purchases preserve those rules: stock allocation and order creation can share one transaction. Then handle lost replies, copied views and operations in other services separately.
Remember these points
- A data model represents facts; indexes and partition keys make particular access patterns efficient.
- Order-line prices are historical facts, so copying the agreed price is deliberate modeling rather than accidental duplication.
- ACID consistency means preserving application rules; it is different from CAP linearizability.
- An atomic conditional stock decrement must be checked for success and committed with the order.
- A stable customer-scoped purchase key and matching request data recover duplicate or uncertain attempts.
Interview tips
- Write one important read query and one multi-record invariant before naming a database product.
- Act out two concurrent buyers with stock equal to two; identify the lock, predicate recheck, and zero-row outcome.
- When splitting services, redraw the transaction boundary before discussing horizontal scaling.
Important qualifications
- Read Committed behavior in the worked SQL is PostgreSQL-specific; verify another engine before transferring that proof.
- Transactions and isolation levels vary within both relational and NoSQL families.
- The SQL excerpt omits table creation and production error handling; its affected-row branch is required application logic.
Technical references
- PostgreSQL: Transaction IsolationVerified reference for isolation behavior and serialization retries.
- MongoDB: TransactionsVerified example of document-store multi-document transactions.
- Apache Cassandra: Logical Data ModelingOfficial reference for query-driven tables, partition keys, and clustering columns; more directly relevant to the wide-column comparison than placement architecture.
- Oracle Database Concepts: database and DBMSBasic distinction between an organized data collection and the software managing it.
- PostgreSQL tutorial: TransactionsIntroduces transactions as all-or-nothing units, then explains concurrent visibility and durability.
Practice marks stay in this browser.