
Serverless Portability Claims Rarely Survive Contact With a Real Migration
Key takeaway: The function code itself is often the smallest part of what would need to change in a serverless migration. The surrounding integration — triggers, permissions, deployment — is where the real coupling lives.
Where the Coupling Actually Sits
A function’s business logic — parse this input, call this downstream service, return this response — genuinely can be written in a fairly portable way, and this is the part most articles about serverless portability focus on. It is also usually the smaller part of the actual migration effort.
The event that triggers the function, the format that event arrives in, the permission model granting the function access to other resources, and the tooling used to deploy and configure it are all typically provider-specific, and none of them are addressed by writing portable handler logic. A function triggered by a storage event receives a payload shaped entirely by that provider’s storage service, and a function migrating to a different provider needs that payload parsing rewritten regardless of how portable the core logic was.
What Actually Differs Between Providers
| Component | Portability |
|---|---|
| Core business logic in the handler | High, if written deliberately |
| Event payload format from triggers | Low — provider-specific structure |
| IAM / permission binding model | Low — each provider’s own model |
| Deployment and configuration tooling | Low — provider-specific by default |
| Cold start and concurrency behaviour | Varies significantly, affects design |
| Managed integrations (queues, storage, database triggers) | Low — tightly coupled by design |
Managed integrations are usually where the real lock-in concentrates, and they are also usually the reason serverless was chosen in the first place — a function reacting directly to a storage upload event with no additional infrastructure to manage is a genuine and valuable capability, and it is also a capability defined entirely by one provider’s specific service and event model.
Reducing Coupling Where It Is Worth the Cost
Structuring the handler as a thin adapter that translates the provider-specific event into an internal, provider-neutral representation before calling into the actual business logic keeps the substantial portion of the code portable, even though the adapter itself still needs rewriting per provider. This is a real and valuable pattern specifically because it isolates the migration cost to a small, well-defined boundary rather than letting provider-specific assumptions leak throughout the business logic.
Using a deployment framework that abstracts some provider differences can reduce tooling-level lock-in for straightforward cases, though it rarely eliminates the need to understand and adjust for genuine differences in event formats and permission models during an actual migration.
When Pursuing Portability Is Not Worth It
For most serverless adoption, the pragmatic and usually correct choice is accepting the coupling in exchange for the operational simplicity serverless is chosen for in the first place — provisioning-free scaling, pay-per-invocation pricing, and managed integration with the provider’s other services. Architecting extensively for portability that will likely never be exercised trades real, immediate simplicity for a hypothetical future flexibility that may never be needed, and that trade is frequently not worth making.
The exception is genuinely business-critical logic where a specific, credible reason to expect a future migration exists — a regulatory requirement for provider diversity, or a pattern of provider instability specific to your situation. Absent a concrete reason, isolating the handler adapter pattern captures most of the reasonable protection without paying the larger cost of avoiding managed integrations altogether.
The Bottom Line
Accept that serverless portability claims rarely hold once event formats, IAM models and deployment tooling are counted, and isolate the provider-specific event handling behind a thin adapter to keep the substantial business logic portable without abandoning valuable managed integrations. Reserve deeper portability investment for the specific cases with a genuine, credible reason to expect a future migration, rather than defaulting to it everywhere.



