Reactive Design Patterns
Roland Kuhn with Brian Hanafee and Jamie Allen
  • MEAP began March 2014
  • Publication in February 2017 (estimated)
  • ISBN 9781617291807
  • 325 pages (estimated)
  • printed in black & white

Reactive Design Patterns is a clearly-written guide for building message-driven distributed systems that are resilient, responsive, and elastic. In it, you'll find patterns for messaging, flow control, resource management, and concurrency, along with practical issues like test-friendly designs. All patterns include concrete examples using Scala and Akka. In some cases, you will also see examples in Java, JavaScript, and Erlang. Software engineers and architects will learn patterns that address day-to-day distributed development problems in a fault-tolerant and scalable way. Project leaders and CTOs will gain a deeper understanding of the reactive design philosophy.

Table of Contents detailed table of contents

Part 1: Introduction

1. Why Reactive?

1.1. The anatomy of a Reactive application

1.2. Coping with load

1.3. Coping with failures

1.4. Making it responsive

1.5. Avoiding the ball of mud

1.6. Integrating non-reactive components

1.7. Summary

2. A walk-through of the Reactive manifesto

2.1. Reacting to Users

2.1.1. Understanding the Traditional Approach

2.1.2. Analyzing Latency with a Shared Resource

2.1.3. Limiting Maximum Latency with a Queue

2.2. Exploiting Parallelism

2.2.1. Reducing Latency by Parallelization

2.2.2. Improving with Composable Futures

2.2.3. Paying for the Serial Illusion

2.3. The Limits of Parallel Execution

2.3.1. Amdahl's Law

2.3.2. Universal Scalability Law

2.4. Reacting to Failure

2.4.1. Compartmentalization and Bulkheading

2.4.2. Using Circuit Breakers

2.4.3. Supervision

2.5. Losing Strong Consistency

2.5.1. ACID 2.0

2.5.2. Accepting Updates

2.6. The Need for Reactive Design Patterns

2.6.1. Managing Complexity

2.6.2. Bringing Programming Models Closer to the Real World

2.7. Summary

3. Tools of the Trade

3.1. The Impact of Choosing Non-Reactive Tools

3.1.1. The Cost

3.2. Functional Programming

3.2.1. Immutability

3.2.2. Side Effects

3.2.3. Referential Transparency

3.2.4. Functions as First-Class Citizens

3.3. Responsiveness to Users

3.3.1. The Cost of Abstractions

3.3.2. Throughput

3.3.3. Latency

3.3.4. Footprint

3.3.5. Prioritizing the Performance Characteristics

3.4. Implementations That Support Reactive

3.4.1. Green Threads

3.4.2. Event Loops

3.4.3. Communicating Sequential Processes

3.4.4. Futures and Promises

3.4.5. Reactive Extensions

3.4.6. The Actor Model

3.4.7. Summary

Part 2: The Philosophy in a Nutshell

4. Message Passing

4.1. Synchronous vs. Asynchronous

4.2. Event-Based vs. Message-Based

4.3. Flow Control

4.4. Delivery Guarantees

4.5. Vertical Scalability

4.6. Events as Messages

4.7. Synchronous Message Passing

4.8. Summary

5. Location Transparency

5.1. What is Location Transparency?

5.2. The Fallacy of Transparent Remoting

5.3. Explicit Message Passing to the Rescue

5.4. The Role of Latency and Throughput

5.5. The Role of Message Loss

5.6. Horizontal Scalability

5.7. Location Transparency makes Testing Simpler

5.8. Dynamic Composition

5.9. Summary

6. Divide and Conquer

6.1. Hierarchical Problem Decomposition

6.2. Dependencies vs. Descendant Modules

6.3. Advantages for Specification and Test

6.4. Build your own Big Corporation

6.5. Horizontal and Vertical Scalability

6.6. Summary

7. Principled Failure Handling

7.1. Ownership means Commitment

7.2. Ownership implies Lifecycle Control

7.3. Resilience on All Levels

7.4. Summary

8. Delimited Consistency

8.1. Encapsulated Modules to the Rescue

8.2. Grouping Data and Behavior According to Transaction Boundaries

8.3. Modeling Work-flows across Transactional Boundaries

8.4. Unit of Failure = Unit of Consistency

8.5. Segregation of Responsibilities

8.6. Persisting Isolated Scopes of Consistency

8.7. Summary

9. Non-Determinism by Need

9.1. Logic Programming and Declarative Data-Flow

9.2. Functional Reactive Programming

9.3. Shared-Nothing Concurrency

9.4. Shared-State Concurrency

9.5. So, What Should We Do?

9.6. Summary

10. Message Flow

10.1. Push Data Forward

10.2. Model the Processes of Your Domain

10.3. Identify Resilience Limitations

10.4. Estimate Rates and Deployment Scale

10.5. Plan for Flow Control

10.6. Summary for Part 2

Part 3: Patterns

11. Testing Reactive Applications

11.1. How To Test

11.1.1. Unit Tests

11.1.2. Component Tests

11.1.3. String Tests

11.1.4. Integration Tests

11.1.5. User Acceptance Tests

11.1.6. Black Box Versus White Box Tests

11.2. Test Environment

11.3. Testing Asynchronously

11.3.1. Providing Blocking Message Receivers

11.3.2. The Crux with Choosing Timeouts

11.3.3. Asserting the Absence of a Message

11.3.4. Providing Synchronous Execution Engines

11.3.5. Asynchronous Assertions

11.3.6. Fully Asynchronous Tests

11.3.7. Asserting the Absence of Asynchronous Errors

11.4. Testing Non-Deterministic Systems

11.4.1. The Trouble with Execution Schedules

11.4.2. Testing Distributed Components

11.4.3. Mocking Actors

11.4.4. Distributed Components

11.5. Testing Elasticity

11.6. Testing Resilience

11.6.1. Application Resilience

11.6.2. Infrastructure Resilience

11.7. Testing Responsiveness

11.8. Summary

12. Fault Tolerance and Recovery Patterns

12.1. The Simple Component Pattern

12.1.1. The Problem Setting

12.1.2. Applying the Pattern

12.1.3. The Pattern Revisited

12.1.4. Applicability

12.2. The Error Kernel Pattern

12.2.1. The Problem Setting

12.2.2. Applying the Pattern

12.2.3. The Pattern Revisited

12.2.4. Applicability

12.3. The Let-It-Crash Pattern

12.3.1. The Problem Setting

12.3.2. Applying the Pattern

12.3.3. The Pattern Revisited

12.3.4. Implementation Considerations

12.3.5. Corollary: the Heartbeat Pattern

12.3.6. Corollary: The Proactive Failure Signal Pattern

12.4. The Circuit Breaker Pattern

12.4.1. The Problem Setting

12.4.2. Applying The Pattern

12.4.3. The Pattern Revisited

12.4.4. Applicability

12.5. Summary

13. Replication Patterns

13.1. The Active—Passive Replication Pattern

13.1.1. The Problem Setting

13.1.2. Applying The Pattern

13.1.3. The Pattern Revisited

13.1.4. Applicability

13.2. Multiple-Master Replication Patterns

13.2.1. Consensus-Based Replication

13.2.2. Replication with Conflict Detection and Resolution

13.2.3. Conflict-Free Replicated Data Types

13.3. The Active—Active Replication Pattern

13.3.1. The Problem Setting

13.3.2. Applying The Pattern

13.3.3. The Pattern Revisited

13.3.4. The Relation to Virtual Synchrony

13.4. Summary

14. Resource Management Patterns

14.1. Resource Encapsulation Pattern

14.1.1. The Problem Setting

14.1.2. Applying the Pattern

14.1.3. The Pattern Revisited

14.1.4. Applicability

14.2. Resource Loan Pattern

14.2.1. The Problem Setting

14.2.2. Applying the Pattern

14.2.3. The Pattern Revisited

14.2.4. Applicability

14.2.5. Implementation Considerations

14.3. The Complex Command Pattern

14.3.1. The Problem Setting

14.3.2. Applying the Pattern

14.3.3. The Pattern Revisited

14.3.4. Applicability

14.4. The Resource Pool Pattern

14.4.1. The Problem Setting

14.4.2. Applying the Pattern

14.4.3. The Pattern Revisited

14.4.4. Implementation Considerations

14.5. Patterns for Managed Blocking

14.5.1. The Problem Setting

14.5.2. Applying the Pattern

14.5.3. The Pattern Revisited

14.5.4. Applicability

14.6. Summary

15. Message Flow Patterns

15.1. The Request—Response Pattern

15.1.1. The Problem Setting

15.1.2. Applying the Pattern

15.1.3. Common Instances of the Pattern

15.1.4. The Pattern Revisited

15.1.5. Applicability

15.2. The Self-Contained Message Pattern

15.2.1. The Problem Setting

15.2.2. Applying the Pattern

15.2.3. The Pattern Revisited

15.2.4. Applicability

15.3. The Ask Pattern

15.3.1. The Problem Setting

15.3.2. Applying the Pattern

15.3.3. The Pattern Revisited

15.3.4. Applicability

15.4. The Forward Flow Pattern

15.4.1. The Problem Setting

15.4.2. Applying the Pattern

15.4.3. The Pattern Revisited

15.4.4. Applicability

15.5. The Aggregator Pattern

15.5.1. The Problem Setting

15.5.2. Applying the Pattern

15.5.3. The Pattern Revisited

15.5.4. Applicability

15.6. The Saga Pattern

15.6.1. The Problem Setting

15.6.2. Applying the Pattern

15.6.3. The Pattern Revisited

15.6.4. Applicability

15.7. The Business Handshake Pattern

15.7.1. The Problem Setting

15.7.2. Applying the Pattern

15.7.3. The Pattern Revisited

15.7.4. Applicability

15.8. Summary

16. Flow Control Patterns

16.1. The Pull Pattern

16.1.1. The Problem Setting

16.1.2. Applying the Pattern

16.1.3. The Pattern Revisited

16.1.4. Applicability

16.2. The Managed Queue Pattern

16.2.1. The Problem Setting

16.2.2. Applying the Pattern

16.2.3. The Pattern Revisited

16.2.4. Applicability

16.3. The Drop Pattern

16.3.1. The Problem Setting

16.3.2. Applying the Pattern

16.3.3. The Pattern Revisited

16.3.4. Applicability

16.4. The Throttling Pattern

16.4.1. The Problem Setting

16.4.2. Applying the Pattern

16.4.3. The Pattern Revisited

16.5. Summary

17. State Management and Persistence Patterns

17.1. The Domain Object Pattern

17.1.1. The Problem Setting

17.1.2. Applying the Pattern

17.1.3. The Pattern Revisited

17.2. The Sharding Pattern

17.2.1. The Problem Setting

17.2.2. Applying the Pattern

17.2.3. The Pattern Revisited

17.2.4. Important Caveat

17.3. The Event-Sourcing Pattern

17.3.1. The Problem Setting

17.3.2. Applying the Pattern

17.3.3. Revisiting the Pattern

17.3.4. Applicability

17.4. The Event Stream Pattern

17.4.1. The Problem Setting

17.4.2. Applying the Pattern

17.4.3. The Pattern Revisited

17.4.4. Applicability

17.5. Summary


Appendix A: Diagramming Reactive Systems

A.1. Defining the Stencils

Appendix B: An Illustrated Example

B.1. Geographic Partitioning

B.2. Planning the Flow of Information

B.2.1. First Step: Accepting the Data

B.2.2. Second Step: Getting the Data to their Geographical Home

B.2.3. Step Three: Relocating the Data for Efficient Querying

B.2.4. Taking Stock

B.3. What if something fails?

B.3.1. A Client Fails

B.3.3. A Data Ingestion Front-End Node Fails

B.3.5. A Map Tile Processing Node Fails

B.3.6. A Summary Map Tile Fails

B.3.8. A Map View Front-End Node Fails

B.3.9. Failure Handling Summary

B.4. What have we learnt from this example?

B.5. Where do we go from here?

Appendix C: The Reactive Manifesto

C.1. Main text

C.2. Glossary

C.2.1. Asynchronous

C.2.2. Back-Pressure

C.2.3. Batching

C.2.4. Component

C.2.5. Delegation

C.2.6. Elasticity (in contrast to Scalability)

C.2.7. Failure (in contrast to Error)

C.2.8. Isolation (and Containment)

C.2.9. Location Transparency

C.2.10. Message-Driven (in contrast to Event-Driven)

C.2.11. Non-Blocking

C.2.12. Protocol

C.2.13. Replication

C.2.14. Resource

C.2.15. Scalability

C.2.16. System

C.2.17. User

About the Technology

Modern distributed applications must deliver near-realtime performance while at the same time managing big data and high user loads spread across environments ranging from cloud systems to mobile devices. Unlike traditional enterprise applications which focus on decoupling their internal components by defining programming interfaces, reactive applications go one step further and decouple their components also at runtime. This makes it possible to react effectively and efficiently to failures, varying user demands, and changes in the application's execution environment. The resulting systems are highly concurrent and fault-tolerant, with minimal dependencies among individual system components. This is achieved by blending the use of message-passing concurrency between distributed computational units with the robustness of functional programming techniques within them.

About the book

The design patterns in this book were collected by the consultants and engineers of Typesafe during thousands of hours spent building enterprise-quality applications using Scala and Akka. Although many reactive patterns can be implemented using standard development tools like Java, others require the capabilities offered by a functional programming language like Scala and an Actor-based concurrency system like Akka.

What's inside

  • Learn about reactive system design entails and the theory behind its principles
  • Discover best practices and patterns for building reactive applications
  • Build applications that can withstand hardware or software failure at any level
  • Fully utilize multicore hardware using asynchronous and message-driven solutions
  • Scale applications under tremendous load up and down, in and out

About the reader

Readers should be familiar with a standard programming language like Java, C++ or C# and be comfortable with the basics of distributed systems. Although most of the book's examples use the Scala language, no prior experience with Scala or Akka is required.

About the authors

Dr. Roland Kuhn leads the Akka team at Typesafe. Together with Martin Odersky and Erik Meijer, Roland presented the Coursera course "Principles of Reactive Programming" and co-authored the Reactive Manifesto. Brian Hanafee is a Principal Systems Architect at a large financial institution, with experience building reliable and secure web-based applications and backing services for millions of customers. Jamie Allen is the Director of Consulting for Typesafe and author of Effective Akka.

Manning Early Access Program (MEAP) Read chapters as they are written, get the finished eBook as soon as it’s ready, and receive the pBook long before it's in bookstores.
MEAP combo $49.99 pBook + eBook
MEAP eBook $39.99 pdf + ePub + kindle

FREE domestic shipping on three or more pBooks