a developer's sleight of hand

It is so very satisfying when an abstraction that took you some extra minutes finally pays for itself, and gives you a great start of the weekend.
I just swapped my entire email provider from AWS SES to Resend in under an hour. The actual provider change was about 20 lines of code, because the email system was built behind a simple EmailProvider protocol.
Every part of the application, verification emails, welcome emails, suppression checks, talks to this interface. Nothing knows or cares what sits behind it. I replaced the SESProvider class with a ResendProvider, exposed the same interface using a different SDK under the hood, and rewrote the webhook handler to match Resend's format.
Then I got to happily delete a good chunk of Terraform that was no longer needed. But that was honestly it. Templates, rate limiting, suppression list, token generation,none of it changed. Zero modifications to any business logic.
The pattern is straightforward, and very tempting to break. You define a protocol that describes what your application needs from the dependency, not what the dependencyoffers. Sending an email, checking a suppression list, handling a bounce.
Then you write a thin adapter that maps the provider's SDK to that protocol. Your application only ever imports the protocol. The key is being disciplined and keeping the adapter thin, forever. No business logic in it, no special handling, no magic ingrained.
The moment you start putting decisions in the adapter, you have coupled yourself to the provider again, just with extra steps.
This applies well beyond email. Payment processors, notification services, storage backends, anything where a third party owns the implementation. If you can swap it by writing one new class and deleting the old one, you have done the work right.