We had three weeks to migrate file storage from AWS S3 to Azure before our AWS contract renewed. The codebase had a clean storage abstraction built for exactly this scenario. We almost shipped without checking whether everything actually used it.
File exports weren't a background feature — customers downloaded invoices, reports, and audit records through them. A broken export that fails silently doesn't produce an error page. It produces a missing file when someone needs it most.
You're the lead engineer at a B2B SaaS company. You have three weeks to migrate file storage from AWS S3 to Azure before your AWS contract auto-renews at a rate leadership won't approve. The codebase has a storage abstraction layer — an enum-routed system designed years ago with exactly this kind of migration in mind. It looks clean. How do you approach it?
No hints. Just judgment.
Most engineers start a cloud storage migration by updating the abstraction layer and deploying — it feels clean because the abstraction was designed for exactly this. But that collapses two separate risks into one deployment: whether all traffic actually flows through the abstraction, and whether the new backend behaves identically under real load. An audit addresses the first. A hard cutover leaves you exposed on the second. Both need to be solved in the design before you write a line of migration code.