Opening a web page takes a DNS lookup, a TCP handshake, a TLS handshake, and a trip through load balancers, caches, app servers and databases. Follow one real request, measured step by step, and see where the time goes.
Fast” and “reliable” can’t be designed for; p99 under 300 ms and 99.9% of requests succeeding can. Learn percentiles, tail latency, why busy servers get slow, availability nines, SLOs, and back-of-the-envelope estimates.
TCP gives order and reliability at a cost; UDP gives neither. Learn head-of-line blocking, slow start, HTTP/1.1 vs HTTP/2 vs HTTP/3 measured on a lossy network, connection pools and ports, and when to use polling, SSE or WebSockets.
An API is a contract you can’t easily take back. Learn HTTP method and status semantics, Problem Details errors, ETags against lost updates, idempotency keys tested on PostgreSQL, offset vs cursor pagination measured, and when REST, gRPC or GraphQL fits.
A repeatable method for any system design, at work or in an interview. Clarify requirements, estimate, define the API and data, draw the high-level design, go deep on the risky part, and name the trade-offs, worked through a ticket on-sale on PostgreSQL.
What makes a change cheap or expensive. Parnas’s information hiding, rebuilt in Go and measured; coupling and cohesion as first defined in 1974; deep and shallow modules; DRY as knowledge; and how C#, Java, Go and Rust enforce a module boundary.
What each SOLID principle originally said, who said it, and how it gets misread. Liskov substitution broken in running code and in Java and .NET’s own libraries, dependency inversion measured with the Go build tool, and each principle in C#, Java, Go and Rust.
Why implementation inheritance breaks, shown in running Java code; how interfaces, Go’s embedding, Rust traits and plain functions abstract without it; and what static and dynamic dispatch cost, measured in Rust, Go and C#.
How to design types so impossible data can’t be built: sum types, exhaustive matching, newtypes, parsing at the boundary and typestate, in C#, Java, Go and Rust, with what each compiler actually says when a case is missed.
How C# and Java exceptions, Go’s error values and Rust’s Result carry one failure through a service, what each compiler checks, what failure costs, measured, and where to handle errors, log them and turn them into responses.
Locks, atomics, channels, ownership and actors compared on one counter in C#, Java, Go and Rust, measured; what a data race really is, which bugs each model makes impossible, and which it quietly keeps.
Strategy, adapter, decorator, middleware, observer, builder and state machines in C#, Java, Go and Rust, with the patterns each language feature deleted, and a measured look at what changes when you add a case.
What layered, hexagonal and clean architecture really say, where they disagree, and how dependencies get inverted in C#, Java, Go and Rust, with .NET’s container lifetimes and captive dependencies shown in running code.
Designing a rate limiter from requirements to API: token bucket against fixed window with the boundary burst measured, an injected clock, thread safety, and what .NET, Java, Go and Rust’s libraries really do.
A cache from first principles: a map plus a recency list, TTLs without a timer per key, LRU against sampled and random eviction measured on a Zipf workload, and the stampede that takes your database down.
Pages, write-ahead logs, B-trees and LSM-trees, with write, read and space amplification measured on a page store and a miniature LSM, and PostgreSQL 18 measured on page layout, HOT updates, bloat and WAL bytes.