Whatever you choose, the second migration should be cheaper than the first. That's a code decision, not a platform one.
Keep business logic in plain functions that take inputs and return outputs, with platform specifics in thin adapters at the edge. Code written against standard Request and Response objects moves between every platform on this page. Code that reaches for a provider's caching helpers, environment magic or proprietary storage bindings does not.
Prefer standard interfaces where a standard exists: S3 for object storage, Postgres
for the database, plain HTTP for everything else. Every one of those has a dozen providers, which means every one of them is a price negotiation rather than a lock-in.
Watch out for the small dependencies that quietly pin you: an image optimisation endpoint, a KV store with a proprietary API, an authentication integration that assumes the platform's environment. Each is individually trivial and collectively the reason a migration takes a month instead of a week.
Finally, check regions before price. Serving Australian users from a US region adds a couple of hundred milliseconds to every uncached request, and no pricing model compensates for that.