Often, our instinct is to build for optionality. What if we change databases? What if we change clouds? We target the Least Common Denominator (LCD) interface to avoid vendor lock-in and make sure our software is portable – after all, Optimization is Fragile. LCD interfaces look like targeting the S3 API, a generic PubSub implementation, or vanilla ANSI SQL.

LCD interfaces are good enough most of the time, but when we need to run a specialized workload, sometimes they don't perform how we'd like. We could solve our problem quickly by narrowing the API – coupling it to a specific cloud or managed service, but that destroys our optionality. Here, you should probably fight your instinct to stick with the pure implementation and weigh the trade-offs – how many developer-hours and pain can you save by narrowing the interface?

Optimization and optionality are inherent trade-offs. There's a way to architecture services to be efficient and generic but also practical.

But switching costs are real and shouldn't entirely be forgotten. If you have to use a platform-specific feature or product, isolate the lock-in as best you can, or chart a path to a more generic interface (Don't Use Kubernetes, Yet). You might migrate some workloads to a specialized database or use a different cloud for a particular function (e.g., AI APIs on Google Cloud).