Building Software

Engineering Fundamentals for the Agent Era

Contents Section 6, Design

Where Logic Meets the Database

Mistakes to catch in review

  1. N+1 queries: one query for a list and then one more for every item, usually hidden inside an ORM's lazy loading.

  2. Uniqueness checked only in application code, so two simultaneous requests both pass the check and create duplicates.

  3. A whole table fetched into memory to be filtered or sorted in code instead of in the query.

  4. The same business rule written in both a query and application code, drifting apart over time.

The boundary between application code and storage: where business rules live, what queries get generated, and how the two stay consistent.

Topics

Rules in Code and in Constraints
Using database constraints for invariants that must never break, and application code for rules that need context.
ORMs and Query Builders
What object-relational mappers generate, when they help, and when to write the query yourself.
Query Shape and the N+1 Problem
Designing data access around what a page or job actually needs, in as few round trips as possible.
Transaction Boundaries
Deciding which changes must commit together, and keeping slow network calls out of open transactions.
Data Access Layers
Keeping storage details behind one module so schema changes don't ripple through the codebase.

You understand it when you can

  • Read the query log for one page load, count the queries and explain each one.
  • Decide whether a given rule belongs in a database constraint, in application code or in both, and justify it.
  • Rewrite an N+1 access pattern as a single query or a batched load and measure the difference.

Drill

An agent built a team dashboard that loads teams through an ORM, then lazily loads each member's recent tasks inside a loop, and enforces unique team names by looking the name up before inserting. Count the queries for a page showing 30 teams of 8 people, and find the race that still creates duplicate names.

Start here

Watch

Read

SQL Antipatterns, Volume 1: Avoiding the Pitfalls of Database Programming

Bill Karwin, 2022.

Each chapter takes a plausible-looking pattern (keyless entries, rules kept only in application code, fetching everything and filtering in code) and shows the cost it hides and the constraint or query that fixes it.

Patterns of Enterprise Application Architecture

Martin Fowler, 2002.

The source for the patterns underneath every ORM (Active Record, Data Mapper, Unit of Work, Lazy Load, Repository), which explains where N+1 queries come from and how a data access layer hides the schema.

Primary sources

  • Manual

    PostgreSQL Documentation: Constraints

    Documents check, not-null, unique, primary-key, foreign-key and exclusion constraints, the database-side rules that hold under concurrent writes where an application-side check does not.

  • Manual

    Django Documentation: Database access optimization

    Official guidance on profiling queries, doing work in the database instead of in Python, and fixing N+1 access with select_related and prefetch_related. The same ideas carry over to any ORM.