I love how simple the world works.
On the drive into work, traffic is always moving perfectly.
When I arrive at my desk, I have all my previous days tasks completed, and all of today’s tasks prepared.
Everytime I send someone an email, I receive an instant response and it always contains the information I needed.
Meetings start on time and everyone invited shows up prepared.
I doubt any person in the world could actually say their days were like that, but many times this is how we design software.
We expect that everything will always run in a reliable and calculated way.
I have seen very skilled and talented developers hit a mental roadblock when they move from synchronous systems to asynchronous ones.
Keep in mind that the real world forces us to cope with the unexpected every day. You can not safeguard your systems from all failures, delays or other unexpected errors. You can however put plans in place to cope with these events.
Do not ignore the complexities of asynchronous systems, deal with them head on.
As a benefit, your systems will model explicitly these coping and reconciliation scenarios.