Posts in this series:
- A Primer
- Document Coordination
- Document Example
- Dispatching Example
- Failures and Retries
- Failure Recovery
- Relational Resources
We started out with a common, but nearly always overlooked problem: how do we reliably coordinate activities between different transactional resources? The question we need to ask first is - do we need to coordinate these activities?
Ultimately, it's a business decision about how to deal with the messiness of a distributed world. We have resources we expect to behave transactionally (a single SQL database), resources we might assume to behave transactionally (multiple writes to a document database), and resources we should never assume to behave transactionally (disparate resources, such as a database and a queue). We have a responsibility to help inform and instruct the business on benefits and drawbacks, risks and upsides to each approach.
NoSQL databases themselves are moving towards allowing greater consistency guarantees, both within a single node and multi-node. The onus is still on the developer to understand the transactional guarantees and options available, so that our system still behaves as expected.
"Solving" the transactional challenge against multiple resources ultimately involves a variety of patterns and techniques, the end result being naturally more complex than when we started. This is natural, however. Resource coordination is a feature, naturally requiring more code to address. We can reduce the intrusion of infrastructure concerns into our business logic by using patterns like domain events, aggregates, and outbox.
Because addressing the transactional challenge ultimately affects the user experience, especially since partial success/failure is a distinct possibility, we can't just independently decide what the "right" solution is. From experience, I can guarantee that the "right" solution isn't ignorance - things do fail in production.
So what is the "right" solution? It all comes down to the consultant's motto: