Every "should we leave AWS" conversation I've sat in starts with a spreadsheet comparing hardware cost per vCPU against on-demand pricing. That spreadsheet is usually right, and it's also the least important part of the decision. The real cost of running your own infrastructure doesn't show up in a price-per-core comparison. It shows up eight months later, at 3am, when a disk fails in a way your runbook didn't cover.
This is the checklist I actually use with clients weighing private cloud or bare-metal Kubernetes against staying on a hyperscaler. It's not exhaustive, and I'll keep amending it as we run into new failure modes worth adding, because a list like this written once and left alone stops being useful the first time it's wrong.
The checklist
| Consideration | What it actually means | What it costs you if you skip it |
|---|---|---|
| Storage failure | Your storage layer (Ceph, local NVMe, whatever) has its own failure modes, rebuild times, and recovery procedures that have nothing to do with your app's failure modes | Losing a node during a rebuild window and finding out your redundancy math assumed a rebuild speed you don't actually have |
| Backup restore times | Backups exist; restore drills usually don't | A "we have backups" answer in an incident that turns into an 11-hour restore because nobody ever timed it |
| Upgrade paths | Kubernetes, your CNI, your storage driver, and your OS all have independent release cadences and compatibility matrices | A security patch you can't apply without also upgrading three other things you weren't planning to touch this quarter |
| Capacity headroom | You're now responsible for buying ahead of demand, not autoscaling into it | A six-to-twelve week hardware lead time standing between you and the traffic spike that's happening right now |
| On-call | Someone now owns the hardware, not just the app | A 2am page for a failed power supply going to the same three engineers who already owned app on-call |
| Egress | Moving data off your own infrastructure is often the one thing that got cheaper by leaving AWS, but only if you actually re-architected around it | Building a hybrid setup that still routes traffic through the cloud provider you were trying to get cheaper than |
| Inter-DC latency | Your app's assumptions about "the database is close" may have been quietly true only because you were in one AWS region | A p99 latency regression that shows up in production and nowhere in staging, because staging never crossed a real WAN link |
| Compliance | Your compliance posture partly relied on AWS's SOC 2, and you inherited none of that by moving to your own racks | An audit finding that assumes controls exist which used to live entirely in someone else's shared-responsibility model |
The ones that actually get people
Storage is the one I'd put money on being underestimated most often. Teams size their storage cluster for capacity and IOPS, run the numbers, and call it done. What they don't do is simulate a rebuild under production load. Ceph rebuilding a failed OSD while your app is still hitting it for reads behaves nothing like Ceph at rest, and the first time most teams learn this is during an actual failure, not a test.
Backup restore times are close behind, and for a dumb reason: backups are easy to verify exist and hard to verify work. aws backup or a nightly pg_dump job showing green in your monitoring tells you the backup ran. It tells you nothing about how long a restore takes, or whether the restore procedure even still matches your current schema. I ask clients when they last actually restored from backup onto a clean environment, and about half the time the honest answer is "never."
Capacity headroom is the one that catches people off guard because it's not really a technical problem, it's a change in who's accountable for a decision that used to be invisible. On a hyperscaler, capacity is someone else's problem you pay a premium for. On your own hardware, running low on capacity means a purchase order, a lead time, and a person whose job it now is to watch a trendline and order servers before you need them. I've seen teams get this exactly backward, over-provisioning by 3x out of fear, then justifying the whole "we could've just stayed on AWS" argument by accident.
Egress is the strange one because it's genuinely the best argument for leaving AWS, and also the one most likely to quietly get undone. I've watched a client build out private infrastructure specifically to escape egress costs, then keep a chunk of their data pipeline routed back through their old AWS account because a third-party integration only spoke to S3. Six months in, they were paying for two clouds' worth of egress and hadn't noticed.
Compliance deserves more attention than it gets in these conversations, because it's the one where the cost isn't operational, it's organizational. When you're on AWS, a meaningful slice of your compliance story is "AWS is SOC 2 Type II, here's the report." Move to your own infrastructure and that sentence disappears from your audit response. Physical access controls, environmental monitoring, hardware disposal procedures: someone on your team now owns documenting and proving all of it, and that someone is usually not identified until the audit is already scheduled.
What this list is for
None of this is an argument against private cloud. I've run this exact migration for clients where it was clearly the right call, and the AWS bill they'd been paying was genuinely irrational for their workload. It's an argument against making the decision on a hardware cost comparison alone, because every item on that table above is a real operational cost that a spreadsheet comparing dollars per core will never show you.
If you're in the middle of this decision, the honest move is to go through each row and write down, specifically, who on your team owns it today and who would own it after the move. If a row doesn't have an owner, that's not a reason to stay on AWS. It's just the actual cost of the decision you're about to make, and it's worth knowing before you make it rather than after.