CHAPTER 04FIELD GUIDE

System Design

Migrations, caching, architecture, learning resources, and trade-offs.

🎓
CHAPTER OVERVIEW

7 Lesson Sections • ~6 min read • 1,161 words.

🎓
WHY THIS MATTERS

Deep mastery of this section gives you an immediate advantage in architectural decisions and technical interviews.

STEP 01

Schema/column migrations (dual-write pattern)

A detailed thread walked through why you write to both the old and new column/field during a migration, rather than migrating all data first:

  • Writing to the new field immediately (dual-write) lets you start populating new-feature data right away as the app naturally generates it, reducing how much historical backfill you need to do later, and lets you validate the change is working incrementally.
  • During the transition window, you don't need to query both columns - application code can be updated to read from the new column once it's sufficiently populated, while writes continue going to both.
  • Simpler-sounding alternatives (e.g., just treating the new field as an immediate full replacement) carry real risk (data loss/inconsistency for anything not yet migrated); adding a new column and dual-writing is the safer, if slightly more effort-intensive, default pattern.
STEP 02

Caching and cache invalidation trade-offs (real product example)

an industry expert described the actual trade-off space his team faces for a "stats" screen with felt latency:

  • The hard part isn't picking a cache technology (e.g., Redis) - it's deciding how aggressively to cache on-device and how/when to invalidate.
  • Concrete open questions his team was weighing: Should completing a question trigger a full reload from the DB, and how much of it? Should navigating between screens always re-fetch, or only after some elapsed time? Should the UI update optimistically, and if so, does that create a risk of users manipulating their own client-side stats?
  • An experienced professional's counter-proposal (a good general UX-latency heuristic worth reusing broadly): always keep some data fresh-on-load for correctness, but if the user returns to a screen within a very short window (e.g., <2 seconds) don't force a full reload - preserve scroll position/state like DoorDash does when you back out of a restaurant page quickly, but do reload if it's been a longer gap.
STEP 03

System design book & resource recommendations

  • Designing Data-Intensive Applications (DDIA) was repeatedly endorsed as the standout book, referenced by multiple unrelated experienced professionals across different channels (informally "the boar book," referring to its cover).
  • the field observation on the genre: most "system design" reading material skews toward interview prep rather than real production war-stories, because a lot of production system-design knowledge is tacit/experience-based rather than written down formally. Suggested ways to fill that gap: engineering blogs from major infra-heavy companies (which publish real production post-mortems and design write-ups), and treating system design study as a more ad-hoc, blog-driven learning space compared to something structured like DSA.
  • Specific links shared:
    • A curated list: "I read 25 system design books, here are the 11 that actually made me a better engineer" (dev.to)
    • github.com/ashishps1/awesome-system-design-resources
    • github.com/donnemartin/system-design-primer
    • hyrumslaw.com - Hyrum's Law ("with a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody") - shared as generally relevant background reading for API/system design thinking.
  • On learning specific patterns hands-on: it's rare to actually implement core infra primitives from scratch on the job (e.g., writing your own load balancer). If you want that experience anyway, NGINX's source (github.com/nginx/nginx) is a good, heavily-used real codebase to explore. For practical integration patterns, reading the provider docs directly is more useful than a textbook: AWS ALB docs, Google Cloud HTTPS load balancing docs, NGINX load-balancing docs were all shared as concrete references.
  • For learning Kubernetes basics specifically: k8sgames.com was shared as a lightweight, game-based way to get oriented, alongside the official Kubernetes architecture docs (kubernetes.io/docs/concepts/architecture/). Managed-K8s alternatives discussed: AWS EKS (AWS-managed Kubernetes) vs. AWS ECS (more fully managed, avoids dealing with raw K8s directly) vs. Google GKE.
  • General principle repeated by multiple experienced professionals: learn one cloud provider deeply - the core concepts (containers, IaC via Terraform, Kubernetes) transfer to other providers once internalized, so depth in one beats shallow breadth across three.
STEP 04

Database/backend architecture Q&A (marketplace platform case)

An experienced professional building a marketplace-style product asked about Row-Level Security (RLS) trade-offs and connection pooling while self-hosting Postgres on a single VPS:

  • Their stated approach: PgBouncer in transaction mode (cheaper than opening a fresh DB connection per query) plus a combined application-layer authorization filter + Postgres RLS policy to enforce that User A can never read User B's data.
  • Their design instinct to skip caching entirely at the pre-launch stage ("doesn't justify the use yet") was validated by the industry: don't add caching until you actually have real usage/issues to justify the added complexity - this echoes the general "single VPS for app logic + DB in the early stage" pattern referenced elsewhere in the server as prior guidance from an industry expert.
  • Open/unresolved question from that thread: how to weigh RLS's security guarantees against its latency cost specifically on tables involved in heavy joins with sensitive data - flagged in the archive as a live discussion rather than a settled answer.
STEP 05

Interview vs. production depth calibration

An experienced professional asked whether specifying exact technology choices (e.g., "Cassandra" vs. "MongoDB" specifically) matters for system design generally, or just for interviews. Answer: it depends on context, but you should expect to be asked to go deep in at least one section (frequently the database layer) in an interview setting - understanding the underlying concepts well tends to make the specific technology choice follow naturally once you need to commit to one.

STEP 06

Regression testing (raised as an open discussion topic, not fully resolved)

An experienced professional raised regression testing as a rich topic worth a deeper treatment: how do you capture inputs/outputs to a system for regression purposes - at the system boundary or between internal components? Roll your own serialization, or use existing tooling (e.g., Python's pickle, Go's gob)? Serialize to text or binary, and why? an industry expert noted this was a constant, genuinely difficult topic discussed internally during his time at Amazon, without a single settled answer - flagged here as a good topic for further personal research rather than a solved problem.

STEP 07

Learning C++ through a project (practical progression shared by a hackathon builder)

An experienced professional who built a distributed matching-engine benchmarking platform in C++ shared a concrete, reusable progression for learning a systems language through building rather than tutorials:

  1. Build a basic HTTP server, then add routes and logic.
  2. Only then start optimizing specific bottlenecks as they appear - e.g., they initially used the Crow framework for WebSockets (easy to set up) but found it too slow under load and migrated to uWebSockets for performance; similarly moved from nlohmann/json (flexible but slower, more verbose) to glaze (struct-based serialization - faster and less code).
  3. The general lesson: start simple and functionally correct, then replace specific components only once you've identified a real bottleneck, rather than optimizing prematurely.
  • Complementary beginner resources shared: codecrafters.io (project-based systems programming challenges) and learncpp.com.

KEY CHAPTER TAKEAWAYS

01

Writing to the new field immediately (dual-write) lets you start populating new-feature data right away as the app naturally generates it, reducing how much historical backfill you need to do later, and lets you validate the change is working incrementally.

02

During the transition window, you don't need to query both columns - application code can be updated to read from the new column once it's sufficiently populated, while writes continue going to both.

03

Simpler-sounding alternatives (e.g., just treating the new field as an immediate full replacement) carry real risk (data loss/inconsistency for anything not yet migrated); adding a new column and dual-writing is the safer, if slightly more effort-intensive, default pattern.

KNOWLEDGE CHECK

Test your judgment.

Three short decisions to lock in the most useful idea from this chapter.
0 XP 0/10 chapters mastered
QUESTION 01 of 03 +10 XP

During a schema migration, what is the safer first move?