Goal
The path to "Designing Data-Intensive Applications"
Here is the reading path leading up to this book, derived from its dependencies and ordered from the fundamentals.
The path so far (31 books)
Why read this first: SQL Queries for Mere Mortals begins by checking that the database structure is sound, in its second chapter, before any query is written. Having worked through tables, keys and relationships as a design process first, you can read the join and subquery chapters knowing why the tables connect the way they do. Both books belong to the For Mere Mortals series and neither depends on a particular database product.
Why read this first: After learning the correct design procedure, the next step is learning what not to do from cautionary examples. Bill Karwin's 'SQL Antipatterns' systematizes classic failures—missing foreign keys (Keyless Entry), EAV, comma-separated lists—reinforcing from the flip side why enforcing integrity with constraints matters.
Why read this first: After learning structural 'patterns' of distributed systems from Burns's book, advance to the hard part beyond them—data consistency and fault tolerance. Kleppmann's 'Designing Data-Intensive Applications' digs theoretically into replication, distributed transactions, and consensus, providing the data-layer principles that underpin distributed patterns.
Why read this first: Once you can write basic Java syntax, the next step is to raise your sights from merely working code to code that is readable and easy to change. Clean Code provides principles for naming, function decomposition, and comments—building the sense of quality that is hard to acquire on your own.
Why read this first: Once you can write clean functions and classes, it's time to learn design patterns—named solutions to recurring design problems—through Java code. This book lets you experience the 23 GoF patterns in Java implementations, building a vocabulary of reusable designs and the ability to compose relationships between classes with clear intent.
Why read this first: Once you can wield class-level patterns, you broaden your view to how dependencies and boundaries are designed across the whole system. Clean Architecture offers the Dependency Rule—pushing details outward and keeping business rules at the center.
Why read this first: After grasping how networks work, you descend to the OS layer that actually handles that communication. Linux system programming introduces the APIs—sockets, processes, file descriptors—on which servers run, bridging protocol and implementation.
Why read this first: Once you can do basic system programming in Go, you dig deep into concurrency—Go's greatest strength. Concurrency in Go systematizes the design of coordinating 'by communicating rather than sharing memory' using goroutines and channels, teaching how to build safe concurrent programs.
Why read this first: Having understood concurrency within a single process, you extend to a world where multiple processes—services—coordinate asynchronously. Microservices Patterns provides coordination patterns for distributed systems—messaging, sagas, event-driven design—extending the idea of concurrency across the network.
Why read this first: Knowing the OS-level mechanisms for processes, I/O, and memory lets you see what Spring abstracts away under the hood. This low-level understanding keeps the framework from being a black box and pays off when diagnosing performance issues and failures.
Why read this first: Once you can build applications with Spring, you start to feel the limits of framework-driven design centered on the database or the framework. Clean Architecture provides the Dependency Rule that keeps business rules independent of the framework, letting you choose a structure resilient to change over the long term.
Why read this first: Once you can design boundaries inside a system, you face the next decision: whether to split those boundaries into separate processes—services. Monolith to Microservices, guided by the pragmatic 'monolith first' principle, systematizes the motivations, methods, and pitfalls of decomposition.
Why read this first: Once you have a vocabulary of architectural characteristics and trade-offs, you apply that judgment to the concrete case of distributed systems. Microservices demand a design that deliberately breaks coupling in exchange for independent deployment and autonomy.
Why read this first: Once you have the idea of guiding evolution with fitness functions, you advance to concrete analysis of the hard parts of distributed architecture—granularity, data ownership, and communication trade-offs—from the same authors.
Why read this first: Once you understand microservice principles, you advance to realistic strategies for migrating from an existing monolith. Most successes peel services off a monolith incrementally, so you also learn when not to distribute from the start.
Why read this first: Once you can decide whether to split a monolith, you stock up on the implementation patterns needed after the split. Microservices Patterns catalogs the established practices for service decomposition, data management, communication, and deployment, bridging from 'how to divide' to 'how to build.'
Why read this first: Patterns of Enterprise Application Architecture deals with how to layer an enterprise application, organize its domain logic and map objects onto a relational database. Enterprise Integration Patterns takes up what comes next: connecting such applications to each other through asynchronous messaging, in 65 patterns. The two share a way of presenting patterns as a catalog, so the reading habits built on the first book carry over.
Why read this first: Enterprise Integration Patterns organizes messaging channels, message construction, routing, transformation and endpoints with a vocabulary and a visual notation that do not depend on a product. Microservices Patterns takes up the problems that appear once a monolith is decomposed into services: interprocess communication between them, and transactions that span them, handled with sagas. With the messaging vocabulary of the first book in place, the second book's discussion of asynchronous communication can be followed from the ground up.
Why read this first: Learning microservice implementation patterns, you inevitably hit the hard problem of keeping data consistent across services. Designing Data-Intensive Applications supplies the theory of distributed-data consistency, replication, and transactions, underpinning why those patterns work.
Why read this first: When the hard parts of distributed architecture force decisions about decomposing data, you descend to the underlying theory of distributed data. The principles of consistency, replication, and storage engines become the grounds for your design decisions.
Why read this first: Where Karwin's 'SQL Antipatterns' addresses failures at the logical-design and SQL level, this Japanese book addresses RDB pitfalls that surface in production operation. Extending from design-time anti-patterns to operation-time ones gives a full panorama of failure patterns from design through operation.
Why read this first: SQL Queries for Mere Mortals concentrates on how to express SELECT, joins, subqueries and grouping in standard SQL. Once writing a WHERE clause or a join no longer takes thought, SQL Performance Explained picks up the next question about those same clauses: how they use an index.
Why read this first: Once you have the basics of SELECT, the natural next step is set-oriented techniques—CASE expressions, window functions, set operations—that teach you to think in sets rather than procedurally. Both are Japanese SQL books by the same author (Mick), so the vocabulary carries over smoothly from introduction to application.
Why read this first: Once you can write applied SQL, you want to understand why a query is fast or slow from the internal structure of indexes. Markus Winand's 'SQL Performance Explained' builds index design up from how B-Trees work, connecting the way you write SQL with how fast it runs.
Why read this first: Once you study query tuning and index design, you see that many performance problems trace back to early schema and operational decisions. This Japanese book on RDB pitfalls covers operational anti-patterns—soft deletes, caching, idempotency—lifting your view above optimizing individual SQL statements.
Why read this first: Having understood the design of a single relational database, you broaden your view to the big picture of large-scale systems involving multiple data stores. Designing Data-Intensive Applications systematizes the fundamentals of data systems—replication, partitioning, consistency, faults—without being swayed by passing trends.
Why read this first: After grasping RDBMS-agnostic index theory in 'SQL Performance Explained', verify how it is implemented in a concrete product via the Japanese PostgreSQL book. Touching PostgreSQL-specific index types—B-Tree, GiST, GIN, BRIN—and transaction mechanisms lands the abstract theory onto a concrete implementation.
Why read this first: Once you understand one concrete RDBMS implementation (PostgreSQL), you want a map to put it in perspective. Petrov's 'Database Internals' systematizes storage engines and distributed implementations across products, letting you grasp where 'this PostgreSQL mechanism' sits in the general picture.
Why read this first: Only after understanding single-node storage-engine internals do discussions of consistency, replication, and partitioning across multiple nodes become grounded. Kleppmann's 'Designing Data-Intensive Applications' is the capstone that systematizes the principles of distributed data systems, placing internals knowledge as a required prerequisite.
Why read this first: The first part of Understanding Distributed Systems works through TCP, TLS and DNS and ends with a chapter that describes implementing a RESTful HTTP API; the later parts are about scaling a web application with such an API and keeping it running through failures. With HTTP methods, status codes and resource design already familiar, you can read the communication part as review and spend your time on coordination, scalability and resiliency.
Why read this first: The author of Understanding Distributed Systems says himself that the book favors breadth over depth and may not suit readers with years of experience. Replication, partitioning, transactions and consistency models each get a chapter or a section. Designing Data-Intensive Applications spends a whole book on those subjects, and is easier to enter once the first book has given you the vocabulary and a sense of where each piece sits.