Building software for ATMs changed the way I think about reliability. A cash withdrawal looks like one action to a customer, but behind the screen it is a careful negotiation between hardware, networks, ledgers, and uncertain physical outcomes.
The happy path is only the outline
The difficult work lives in interruption: a network timeout after cash is dispensed, a device reporting an ambiguous state, or a reversal arriving later than expected. Each boundary needs an explicit answer to a simple question: what do we know happened?
Idempotency, structured logs, and precise state machines are not architecture decorations in this environment. They are how a team reconstructs truth and protects a customer’s money.
Constraints improve judgment
Older devices and strict protocols encourage deliberate design. I learned to prefer observable systems, small transitions, and boring recovery paths over clever abstractions. Those lessons transfer well beyond financial software.