A couple years ago I went through Ascend, a training taught by one of the heads of Nashville Software School. Docker was the part that stuck first. Being able to spin up machine-learning exercises right on my laptop got me hooked. But the piece that reshaped how I work was optimization.
The lessons were in Python; I work in C#. So I went and relearned all of it in C#: decoupling joins, going asynchronous, streaming results. But that turned out to be the last 10%. The first 90% is almost always a missing index or an N+1 query. The fancy stuff is what you reach for after you’ve stopped doing something obviously slow.
This year my interest quietly shifted. I care less about making things fast and more about making them resilient, about how they behave when something goes wrong.
It started with a bug: bills were failing to load, and the fix needed retries. We reached for Polly. Simple enough, but it got me thinking about the trade-off underneath.
When I first learned about rolling back on failure, I assumed it should always be the move. Then I learned about graceful degradation and swung the other way. Surely the user wants “at least some of the bill saved.” Eventually it clicked: they want neither. They want a smooth way through.
Consider the difference. Fill out a long, intensive form, hit save, watch it fail and clear. That’s infuriating. There, the user wants their effort back, or at least a retry. But a bill loading automatically, in a batch with hundreds of others? A partial save is a false positive: it looks done, no one’s checking, and the missing pieces just quietly vanish.
So there’s no single rule, just the situation. Transient failure on an automated load? Back off and retry, but not forever. A real validation error? Stop and say so. A human mid-task? Save what you can and let them finish. A machine mid-batch? All or nothing, because no one’s watching to catch a partial.
Rollback and graceful degradation aren’t opposites to choose between. They’re both tools, and the situation you’re in usually points to the one the user needs.