Architecture diagrams and trade-offs — what to draw and what to leave out
This chapter covers deciding what boxes and lines represent and the steps to match requirements. It covers how to choose what to leave out, mermaid syntax, showing multiple correct answers for the same requirement (fan-out example), and how to structure a written explanation of the design.
Array scanning patterns — turning a nested loop into a single pass
This chapter organizes four patterns for reducing nested loops to a single pass by applicability. It covers two-pointer, sliding window (fixed and variable), prefix sum for range totals, monotonic stack for "next greater element", and the decision procedure for picking the right one.
Authentication and authorization — proving identity and granting access
This chapter explains the difference between authentication and authorization from the angles of ordering, status codes for failure, and where implementation lives. It covers the three authentication factors, how to carry authentication state via sessions vs. tokens, authorization models like RBAC, and how to structure a written answer.
Availability and redundancy — designing for failure
This chapter covers how to find single points of failure and multiply out availability. Dependencies in series drag availability down; parallel redundancy pulls it up. It covers standby patterns, failover time, degraded operation, and designs that don't turn performance problems into availability problems.
Binary search — halving a sorted array
This chapter explains binary search from the invariant of halving the search range each round. It covers implementation pitfalls (midpoint calculation, boundary conditions, non-shrinking ranges), time and space complexity, why iteration and recursion differ in space, and the conditions under which it applies.
Bit operations — holding flags in bits
This chapter explains bitwise operators (AND, OR, XOR, NOT, shift) and the implementation of bit flags — packing several booleans into a single integer. It covers testing, adding, removing, and toggling flags, building masks, and the point that JavaScript's bitwise operators run on 32-bit signed integers.
Box model — what "width" actually refers to
This chapter covers the CSS box model — the four regions of content, padding, border, and margin, and how box-sizing changes the interpretation of width. It walks through how far the background gets painted, when margin collapsing happens, and the idiom of applying border-box in a reset.
Browser storage — what changes depending on where you put it
This chapter compares localStorage, sessionStorage, and cookies across five axes — whether they reach the server, what separates them, how long they last, how the size limit applies, and whether tabs share them. It covers why the capacity numbers run in opposite directions as floors and ceilings, and where to put authentication tokens.
Capacity estimation — design starts from the numbers
This chapter derives requests per second and data volume from user count. It covers how to place peak multipliers, how the read/write ratio affects the setup, thinking in orders of magnitude, and the conditions under which "one machine is enough" holds.
Chapter 1: The Basic Concept of a Database — Why Keep Data Organized
This chapter frames a database as an organized collection of data and explains, for junior engineers, how that differs from managing data in files or spreadsheets, along with basic capabilities like uniqueness (IDs) and searchability.
Character encoding — how characters map to bytes
This chapter starts from the difference between character set and encoding scheme. It covers four ways of counting characters, normalization for same-looking-different-bytes, collation deciding sort order and comparison, byte-based storage limits, and vulnerabilities from interpretation boundaries being multiple.
Choosing data structures — arrays, lists, stacks, hashes, and trees
This chapter compares arrays, linked lists, stacks, queues, hash maps, trees, and tries by operation complexity. It covers that stacks are LIFO and queues are FIFO, why hash maps average O(1) and what the worst case is, and why tries excel at prefix matching.
Common web attacks and defenses
This chapter organizes major web application attacks — XSS, CSRF, SQL injection — from "conditions that let each succeed" and derives defenses by breaking those conditions. It covers the difference between escaping and placeholders, the relationship between CSRF tokens and SameSite, and why access-control failures rank
Complexity — sizing speed and memory with big-O
This chapter explains big-O by starting from the idea of dropping constant factors and lower-order terms. It covers the feel of common orders, the difference between time and space complexity, how to count orders from loops and recursion, and when to use worst, average, and best cases.
Cookies — who, when, and where they get sent automatically
This chapter organizes cookie attributes by "where to send", "how long to keep", and "who can read", and explains the incidents that arise from the scope not matching origin. It covers that Domain widens into subdomains and that SameSite is evaluated at the site level.
Core Web Vitals — narrowing causes from LCP / INP / CLS
This chapter covers the definitions and thresholds of the three Core Web Vitals (LCP, INP, CLS), and the procedure for narrowing down the cause from combinations of the readings. It explains why slow server responses are not the main cause of poor INP and how CLS worsens with unsized late-arriving content.
Data distribution — what breaks after you spread it out
This chapter covers what replication and sharding gain and break. It explains the difference between sync and async, why you can't read what you just wrote, skew in partition keys, when eventual consistency shows up, and reading CAP as "what to give up during a partition".
Datetimes and time zones — the same instant under different names
This chapter organizes datetime handling into three: instant, local time, and duration. It covers why offsets and time zones are different, how storage differs between past records and future events, that day boundaries move with time zones, that string interpretation changes by form, and pitfalls of calendar arithmetic.
Declarative and imperative UI — deriving UI from state
This chapter contrasts declarative and imperative UI by writing the same screen both ways. It covers why declarative UI reduces the mismatch between state and rendering, where you still need to touch the DOM directly, and what price you pay for it.
Design patterns — four archetypes and their vocabulary
This chapter presents Strategy, Singleton, Observer, and Abstract Factory from the problems each was designed to solve. It covers commonly conflated pairs like Strategy vs. State, Observer vs. polling, and Abstract Factory vs. Factory Method.
DNS — a distributed system that runs on delegation
This chapter explains DNS name resolution as a procedure that walks from a resolver through root, TLD, and authoritative servers. It covers the mechanism of zones and delegation, the relationship between TTL and caching, and what "DNS propagation" actually refers to.
Dynamic programming — never doing the same work twice
This chapter starts from noticing subproblem overlap and derives dynamic programming. It covers the correspondence between memoization and tabulation, the two conditions for applicability, estimating complexity as state count × transition cost, space compression by keeping only the previous row, and the difference from greedy.
Error handling — normal, near-normal, and abnormal paths
This chapter classifies the results of a process into normal, near-normal, and abnormal paths and explains handling for each. It covers the criterion separating expected from unexpected failures, when to use exceptions vs. return values, where to catch, and what to tell users and logs.
Event loop — one thread juggling wait time
This chapter explains how JavaScript juggles both communication and timers on a single thread, from the execution order of tasks and microtasks. It covers when the continuation after await runs, why setTimeout(fn, 0) isn't "immediately", how a long task blocks painting and input, and three directions for offloading heavy processing.
Fundamentals
A hub for the domain covering the layers that run underneath the frameworks, across disciplines. It spans the CSS box model, database locks, DNS, TLS, algorithms, system design, SQL, concurrency, dates, and character encodings.
Graphs and traversal — following the connections
This chapter introduces graph vocabulary and two representations, then explains when to use breadth-first vs. depth-first search. It covers why BFS produces shortest paths without weights, why visited sets are needed, ordering by dependency and detecting cycles with topological sort, and the trick of treating states as vertices.
HTTP — methods, statuses, and headers
This chapter starts from the structure of HTTP requests and responses and then covers the nine standard methods with their safety and idempotency, and the classification of status codes. It covers how to choose between PUT, PATCH, and POST by what the body means, explains that methods appear only on the request line, and why UPDATE and REMOVE are not the ones to use.
HTTP caching and CDNs — designing Cache-Control
This chapter organizes the directives of Cache-Control by "who it applies to", "how long it stays fresh", and "what to do after expiry", and derives caching designs from the nature of the resource. It covers the differences between no-cache and no-store, max-age and s-maxage, where stale-while-revalidate and immutable belong, and why Vary is needed.
IndexedDB and the Cache API — large data, and the conditions for disappearing
This chapter covers IndexedDB and the Cache API for data that does not fit in 5 MiB, starting from the gap between the storage key the spec defines and the key implementations actually use, and from the fact that "stored" and "still there" are not the same. It covers how browsers divide data in third-party contexts and what persist actually means.
Indexes — the cost of making lookups faster
This chapter explains how indexes speed up lookups and the cost they impose on writes. It covers column order in composite indexes, patterns that stop indexes from being used, and how they differ from sharding and hashing.
Joins and aggregation — one answer from many tables
This chapter covers reading and writing queries that join and aggregate across tables. It covers the evaluation order of SELECT, the difference between inner and outer joins captured as row-count changes, one-to-many increasing parent rows, GROUP BY granularity, the difference between COUNT(*) and COUNT(column), NULL three-valued logic, and triaging "the count doesn't add up".
Locks and isolation levels — controlling concurrent execution
This chapter explains shared and exclusive locks, the four transaction isolation levels and three read anomalies, the choice between optimistic and pessimistic locking, and the causes and avoidance of deadlocks. It covers how to hold a version column in the table and why raising the isolation level alone doesn't prevent contention without locks.
Optimistic updates — advancing the UI without waiting for a response
This chapter explains optimistic updates by walking through the flow of advancing the UI on the assumption of success and rolling back on failure. It covers what actually gets faster and what doesn't, when to use it and when not, and why you cannot skip server-side validation.
Origins and CORS — what the browser draws its lines around
This chapter defines an origin as the triple of scheme, host, and port, and explains that the same-origin policy blocks reading, not sending. It covers when preflight is triggered, why wildcard and credentials can't be combined, and why Vary is needed.
Processes and threads — split or share?
This chapter organizes the difference between processes and threads by "split resources or share them". It covers child processes being created as copies of the parent, why environment-variable copies are one-way, that pipe stages run concurrently, race conditions from shared memory, distinguishing CPU-bound from I/O-bound, and terminating with signals.
Recursion and divide-and-conquer — throwing a large problem back at a smaller self
This chapter explains how to design recursion by splitting into a base case and a recursive step. It covers counting work with a recursion tree, that the call stack consumes space, merge sort vs. quicksort as divide-and-conquer, when stable sort is required, and choosing between recursion and iteration.
Rendering patterns — CSR / SSR / SSG / ISR
This chapter organizes CSR, SSR, SSG, and ISR along a single axis — when and where the HTML gets built. It walks through each pattern's trade-offs in initial paint, freshness, SEO, and server load, and the procedure for choosing a pattern from requirements.
Retries and idempotency — telling safe retries apart
This chapter classifies failures into determined, indeterminate, and overload, and derives when a retry is safe from idempotency. It covers why exponential backoff needs jitter, why the ceiling is two values (attempt count and total elapsed time), and what an idempotency key guarantees.
Scaling directions — deciding how to grow
This chapter covers vertical and horizontal — the two directions — and the steps to externalize state so horizontal is possible. It covers what load balancers distribute by and health checks, offloading reads to caches and writes to queues, and the order in which bottlenecks move.
Selectors and cascade — combinators, pseudo-classes, and specificity
This chapter explains the kinds of CSS selectors, the difference between combinators, the distinction between pseudo-classes and pseudo-elements, and how to compute specificity. It covers the ordering between IDs and classes, the fact that the universal selector and combinators don't contribute to specificity, and what the cascade looks at beyond specificity.
Shell basics — pipes and redirection
This chapter starts from the three streams of standard input, standard output, and standard error, and explains when to use pipes vs. redirection. It covers the difference between overwriting `>` and appending `>>`, why standard error doesn't ride pipes, and combinations with grep.
Shell scripting and environment variables — export and process inheritance
This chapter explains the difference between shell variables and environment variables from the angle of whether they're inherited by child processes. It covers what export does, correct use of the env command, the difference between tilde expansion and absolute paths, and how to choose a way to run a script.
Subqueries and window functions — counting across rows
This chapter covers the three positions where subqueries fit, correlated subqueries and EXISTS, writing in reading order with CTEs, and how window functions aggregate without folding rows. It covers the differences between ROW_NUMBER, RANK, and DENSE_RANK, running totals, top-N per group, and support versions per database.
TCP/IP — the layered model and ports
This chapter explains TCP/IP's layered model from the division of labor where IP decides where to deliver and TCP guarantees how it is delivered. It covers the three ranges of port numbers, why the server port is fixed and the client port is variable, and that IANA registration is optional.
The fundamentals of structured data (JSON-LD / schema.org)
The fundamentals of structured data, JSON-LD, and the schema.org Data Model. Its role as a "contract" between search engines and content, the meaning of @context / @type / @id, the type hierarchy and property ranges, and how to embed it in HTML.
TLS and certificates — what you are trusting when you encrypt
This chapter explains that among the three properties TLS guarantees, what the certificate covers is the other side's identity. It covers certificate chain verification, that intermediate certificate delivery is the server's responsibility, what changes with the location of TLS termination, and reading certificate errors.
Transactions — ACID, commit, and rollback
This chapter covers the three basic operations of a transaction (begin, commit, rollback) and the four ACID properties. It explains that rollback affects only your own transaction, that commits can't be undone, and when syntax errors are detected.
Web Engineering Fundamentals Guide
A groundwork guide across web engineering, from the CSS box model through database locks, DNS, shells, TLS, algorithms, system design, reading and writing SQL, concurrency, dates, and character encoding. Instead of framework usage, it covers what runs beneath and the boundaries that separate judgment calls in practice, across 44 chapters.