Stay Responsive: The Reactive Principles, Explained
Responsiveness matters. A lot.
These words above mark the beginning of the first principle of the The Reactive Principles: Stay Responsive. The directive is simple, but not easy: “Always respond in a timely manner”.
What does this mean precisely? It’s a quality that we obviously want in our systems, but it comes only after a significant investment in Reactive principles and patterns.
In this explanatory series, we look at the Reactive Principles in detail and go deeper into the meaning of things. You can refer to the original document for full context as well as these excerpts and additional discussion.
What do we mean by “Responsive”?
"Being responsive is not just about low latency and fast response time, but also about managing changes—in data, usage patterns, context, and environment. Such changes should be represented within the application and its data model, right up to its end-user interactions; reactions to change will be communicated to the users of a component, be they human or programs, so that responses to requests can be interpreted in the right context."
Ok, now this is starting to sound more complex. What kind of changes in data, usage patterns, context, and environment are we talking about here?
It’s not that complex once you get your head around it. To help you get there, let's look at ordering a meal online.
The obvious part of this process is that the actions you take on the website should have near instantaneous feedback. The less obvious, but still important, part is that if the restaurant is out of lettuce, then the side salad should not be an option you can select, or perhaps even see. The even less obvious part is that the order for new lettuce should have been submitted to the produce company when the lettuce was starting to run out.
Only when we holistically look at the complete system can we remain responsive. This restaurant analogy works with the software we make as well. If there is a problem with the “points” tracker, then the rest of the system needs to be responsive either through graceful degradation of services, or, worst case, a failure message. If it is a very busy day the system should not slow down, it could add more servers to accommodate that busy day or delay non-essential work till later.
How Responsive do we have to be?
"Reactive, responsive applications effectively detect and deal with problems. Reactive applications focus on providing rapid and consistent response times. In the worst-case, they respond with an error message or provide a degraded but still useful level of service. This establishes mutually understood upper bounds on response latency and thereby creates the basis for delivering a consistent quality of service. Such consistent behavior in turn simplifies error handling, builds end-user confidence, and encourages further interaction."
What’s an example of a real-world situation here? How is this “mutual understanding” defined?
In the real world we have a number of defined social contracts that allow us to work together. It’s generally accepted that we stop at red lights when driving, wear clothes in public, and cover our mouths when we cough. ;-)
Breaking these social contracts can feel uncomfortable and wrong. In the software world, contracts need to be explicit and we need to work within the tight boundaries of them. We expect messages about customers to be in a specific format; we need to assume the payment process will respond in a maximum of 3 seconds; that a message in a queue may not be processed if it’s a busy day. Those contracts are often also about trade offs: latency vs throughput vs consistency vs availability.
For example, let’s talk about timeouts. Setting this up is hard. What does a timeout mean? What action should be taken if it occurs? How do we compound them? It comes down to defining the right contracts through protocols—if we continue to blindly retry, it will overload a struggling service even more. We need to look at the system holistically to be able to answer these questions, and ensure all components have that mutual understanding on how to act in all situations—during blue skies, failures, service overload, or resource exhaustion.
Responsiveness is everywhere and nowhere
Responsiveness can be elusive since it is affected by so many aspects of the system. It is nowhere and everywhere, influenced by everything from contention, coordination, coupling, data flow, communication patterns, resource management, failure handling, and uncertainty. It is the foundational concept that ties into, and motivates, all of the other principles.
How is Responsiveness presented in the Reactive Manifesto?
Responsiveness is key since if a service can't provide value, in a timely and predictable fashion, then none of the other traits or bells and whistles matter. For all practical purposes, a non-responsive system does not exist. The Reactive Principles elucidates on that core part of the Reactive Manifesto.
When we look at the diagram for the manifesto above, every part eventually supports responsiveness, it’s the key to reactive design. With the principles everyone supports responsiveness as well. Without Elasticity and Resilience Responsiveness cannot be achieved, those needs can be best delivered via a message driven system. Being Reactive is about using the right tools to maintain Responsiveness regardless of what the world throws at you.