Moving VMs to a cloud account is easy. Paying for idle disks, NAT, and chatty logs is what surprises finance.
A typical app we inherit runs on one box: web, MySQL, cron, and backups. The monthly fee is a round number. After lift-and-shift you pay for compute, block storage IOPS, snapshots, a load balancer, a NAT gateway, and egress. None of those line items existed as separate invoices before.
We map the current box before we size instances: CPU steal, disk wait, peak RAM, and whether cron jobs collide with the morning peak. Undersizing the first week looks like a cloud failure. Oversizing by 4× is how a “simple move” doubles the bill.
If the app still does N+1 queries on the hot page, cloud will not fix the morning timeout — it will make it more expensive. We either fix the query path first (see the 600ms work) or we say the move should wait. Hosting a slow app on a larger VM is not a migration plan.
We also refuse “multi-region from day one” unless there is a documented RPO/RTO and someone who will run failover drills. Fake HA is worse than a single region with backups you have restored once.
One region, sized from metrics, backups tested, cost alerts at 50% of the old monthly hosting plus a stated buffer. After 30 days we review idle resources and reserved vs on-demand. That review is part of cloud hosting work — not an optional extra after the cutover party.
If you already moved and the invoice jumped, send the last bill and a description of the app. We will tell you which line items to kill before we talk about Kubernetes.