In this article

We look at why AWS egress fees are no longer the lock-in mechanism people think they are, and walk through the specific managed services (Lambda, DynamoDB, Step Functions, EventBridge, SQS/SNS, Cognito, API Gateway) that actually make leaving AWS hard.


Egress fees are the part of an AWS bill people can point to. It’s a line item, it has a per-GB rate, and it goes up when you try to leave. So it gets blamed for lock-in.

But if you’ve ever tried to actually move an application off AWS, you know the egress bill isn’t what stops you. What stops you is that your application talks to DynamoDB instead of a normal database, your background jobs run as Lambda functions wired into IAM roles instead of a queue you control, and your workflow logic lives in a JSON state machine that only runs on AWS. Egress is the fee you notice. The managed services are the trap you built, one “just use the managed service” decision at a time, over several years.

This is a pattern we see often: people get mad about egress because it’s the visible line item, but the real trap is “just use our managed service, it’s so easy,” multiplied by 20 over a few years. By the time you want to leave, you’re untangling a plate of spaghetti made of SDKs and event semantics, not S3 bandwidth charges. It’s worth taking apart service by service.

Why This Matters Now

AWS’s egress fees stopped being the sharpest tool in the lock-in argument in March 2024. That’s when AWS began waiving data transfer out to the internet for customers who are moving their data off AWS, a change AWS tied to the direction set by the European Data Act. You apply through AWS Support, your account needs to be in good standing with more than 100 GB stored, and eligible customers get a 90-day window to complete the move.

It’s not automatic and it doesn’t cover everything (CloudFront, Direct Connect, Snow Family, and Global Accelerator are excluded), but for a full exit, the biggest single line item on the “cost of leaving” spreadsheet can often be zeroed out. 37signals used exactly this program when it left AWS, and reported that AWS comped roughly $250,000 in egress charges as part of its exit.

That matters because it changes what the conversation about leaving AWS should actually be about. If egress is negotiable and the rest of your infrastructure is EC2, EBS, and RDS, moving is mostly a data migration and a cutover plan. The workloads that get stuck are the ones wired into services with no standard interface: Lambda, DynamoDB, Step Functions, EventBridge, SQS/SNS, Cognito, and API Gateway.

None of these have a wire protocol or query language you can point at another vendor. Each one requires you to write application code against an AWS-specific SDK, an AWS-specific data model, or an AWS-specific event format. That code doesn’t move. It gets rewritten, and rewriting it is where the real migration cost lives.

Cloud repatriation is not a fringe idea anymore. IDC’s June 2024 report, “Assessing the Scale of Workload Repatriation” (Doc #US50903124), found that about 80% of respondents expected to see some level of repatriation of compute and storage resources within the next 12 months. Read that number carefully: it describes organizations moving some portion of their workloads, not a mass exodus. IDC research VP Natalya Yezhkova has noted that less than 10% of respondents report repatriating entire workloads. Most of this is selective, workload-by-workload repositioning, and the workloads that get moved tend to be the steady, predictable ones where cloud elasticity was never actually being used. The workloads that stay are usually the ones with the deepest managed-service coupling, not because they’re the best fit for AWS, but because leaving them is the hardest.

Lambda: The Coupling Is Everything Around the Function, Not the Function Itself

The code inside a Lambda function is usually portable. A Python or Node.js handler that transforms some input and returns some output will run almost anywhere. What doesn’t move is everything wired around it. Each function has an IAM execution role that determines what it can access, a resource-based policy that determines what can invoke it, and, for anything triggered by SQS, DynamoDB Streams, or Kinesis, an event source mapping that hands the function a payload shaped by that specific AWS service. Your handler code ends up full of assumptions about that payload shape and full of boto3 calls to other AWS services.

Migrating off Lambda to something like Knative, OpenFaaS, or a plain container means rewriting the handler signature, replacing the IAM-based permission model with whatever your target platform uses, and rebuilding every trigger. AWS also runs its own runtime deprecation schedule, so even teams with no plans to leave get forced upgrades on AWS’s timeline, not their own. Open alternatives like Knative Functions consume CNCF CloudEvents, a vendor-neutral event standard, which means the same function runs unmodified on any Kubernetes cluster. That portability is the thing Lambda’s convenience trades away.

DynamoDB: The Deepest Trap Is in the Data Model

DynamoDB is the service most likely to fossilize an application in place, because the lock-in isn’t just the API, it’s the schema design. DynamoDB pushes you toward “single-table design,” where you model partition and sort keys around the access patterns you expect to need, before you’ve written any data. Global Secondary Indexes are close to fixed once you’ve built around them. If a new access pattern shows up later, and it always does, the standard remedy is a script that scans and rewrites existing items, because there’s no ALTER TABLE equivalent that fixes this cleanly.

PartiQL gives DynamoDB a SQL-like syntax, but it’s a translation layer, not a query planner. A PartiQL SELECT without a key condition still becomes a full table scan under the hood. None of this maps cleanly onto PostgreSQL, Cassandra, or ScyllaDB. Moving off DynamoDB means redesigning the data model from scratch, rewriting every query against the new model, and running a dual-write and backfill migration while both systems are live. This is usually the single most time-consuming piece of an AWS exit, and it’s rarely about data volume. It’s about the fact that the schema was never really a schema, it was a description of a specific access pattern for a specific application version.

Step Functions: Your Orchestration Logic Lives in a Proprietary Language

Step Functions workflows are written in Amazon States Language, a JSON-based state machine format that only runs on Step Functions. It’s tightly integrated with close to 200 other AWS services, which is exactly what makes it useful and exactly what makes it non-portable. Payloads are capped at 256 KB, which pushes teams toward passing S3 or DynamoDB references through the workflow instead of data directly, adding more AWS-specific plumbing to unwind later.

Open alternatives like Temporal, Apache Airflow, or Argo keep the workflow logic in your own application code rather than in a proprietary state machine definition, which is the main reason teams move to them. One engineering team documented moving off Step Functions to self-hosted Temporal running on EKS and Aurora Postgres, cutting cost by roughly 80% to about $1,500 a month, with the new setup sized to handle several times their current load at a flat cost regardless of traffic.

Getting there required reimplementing every wait and trigger pattern in application code and running the new system in shadow mode against Step Functions before cutting over, which is a fair description of what this kind of migration actually takes.

EventBridge: A Proprietary Envelope Around Every Event

EventBridge wraps every event in its own envelope with required fields like detail-type and source, and routes events using a proprietary schema registry that also auto-generates code bindings for consumers. Unlike Azure Event Grid or Google’s Eventarc, EventBridge doesn’t natively emit events in the CNCF CloudEvents format. You can convert with input transformers, but that’s an extra translation layer bolted onto every integration, not something built in from the start.

If your event-driven architecture is built around EventBridge rules, routing, and the schema registry, all of that has to be replumbed when you leave, because none of it maps onto a standard broker’s configuration model. Moving to Kafka or RabbitMQ means redefining routing logic in a completely different configuration language and rebuilding the schema validation you were relying on EventBridge to provide.

SQS and SNS: A Proprietary API Standing in for a Standard Protocol

SQS is a proprietary HTTP API with no support for AMQP, MQTT, or STOMP. SNS is a proprietary pub/sub layer on top of it. Every producer and consumer in your application talks to these through the AWS SDK, which means every producer and consumer has to be rewritten to talk to something else. Moving to RabbitMQ means replacing boto3 calls with an AMQP library like pika, mapping SQS queues onto RabbitMQ queues and exchanges, and rebuilding SNS fan-out patterns using fan-out exchanges.

None of this is conceptually hard. All of it is line-by-line rewriting across every service that publishes or consumes a message, which on a mature application can be a lot of services.

Cognito: The One Where Yo

u Can’t Just Export Your Way Out

Cognito is the sharpest lock-in on this list because of one specific limitation: it does not let you export user password hashes. They sit in AWS-managed, KMS-encrypted storage, and there’s no API call that hands them back to you. That leaves two options when you leave: force every user to reset their password, or run a lazy migration where Cognito stays live for months while a Lambda trigger re-authenticates and re-hashes each user the next time they log in.

Everything else about Cognito compounds this. Its Lambda triggers, its identity-pool-to-IAM federation through STS, and its non-standard auth flows don’t transfer to a standard OIDC or OAuth2 provider like Keycloak or Auth0 without being reconfigured across every client application that talks to it. Some user pool settings are immutable after creation, which occasionally forces a full pool rebuild rather than a migration.

If your application has any meaningful user base, Cognito is usually the longest single item on the exit timeline, not because the technology is complex, but because you’re migrating live user credentials without being able to see them.

API Gateway: The Front Door That Comes With Its Own Configuration Language

Most Lambda-backed HTTP APIs sit behind API Gateway, which handles routing, request and response mapping, usage plans, and authorization, often via a Cognito authorizer. Moving to an open ingress layer like Kong, NGINX, or Kubernetes Ingress means recreating all of that configuration, plus whatever authorizer logic you were leaning on API Gateway and Cognito to handle together.

It’s rarely the hardest piece on its own, but it’s rarely independent either. It’s usually the last domino, once Lambda and Cognito are already being replaced.

The Pattern Underneath All of These

Every one of these services follows the same shape. It replaces a standard interface (SQL, AMQP, OIDC, a workflow engine you control) with a proprietary one. It couples your application to AWS-specific event payloads and AWS-specific IAM permission models. And it makes the convenience visible immediately while making the exit cost invisible until you’re trying to leave.

Amazon’s own engineering team gave the clearest public example of this. Prime Video’s video-quality monitoring team documented that its original architecture, built on Step Functions, Lambda, and S3, hit account limits because the service performed multiple state transitions for every second of every stream it monitored, and the constant S3 calls between components added further cost. After consolidating the components into a single process and dropping Step Functions and S3 as an intermediary, the team reported that moving to this architecture reduced infrastructure cost by over 90% and increased scaling capacity.

That’s a team with unlimited internal AWS expertise concluding that stitching together managed services was the wrong architecture for a workload that needed to run constantly and predictably. If AWS’s own engineers hit this wall, it’s not a skills problem. It’s what happens when a workload’s actual shape doesn’t match what the managed services were designed for.

The work involved in undoing any of this is consistent across services: rewrite the SDK calls, redesign the data model or event format, replace the IAM-based permission model with something the new platform understands, migrate the data itself, and re-test everything that touches the old integration. None of that shows up on an AWS invoice. All of it shows up in engineering time, which is exactly why it’s easy to underestimate at decision time and expensive to discover later.

Where OpenStack Avoids This Trap Entirely

The reason this pattern doesn’t repeat on an OpenStack-based private cloud is architectural, not just a pricing difference. OpenStack’s core services, Nova for compute, Cinder for block storage, Neutron for networking, and Swift for object storage, are open, community-governed APIs with multiple independent implementations. There’s no single vendor’s SDK to get welded to, because there’s no single vendor. For a deeper walkthrough of how these map to AWS services, see What Your Cloud API Choice Is Actually Costing You.

The bigger point is what runs on top of that infrastructure:

  • Instead of DynamoDB, you run PostgreSQL, Cassandra, or ScyllaDB
  • Instead of SQS, SNS, and EventBridge, you run Kafka or RabbitMQ
  • Instead of Step Functions, you run Temporal, Airflow, or Argo
  • Instead of Cognito, you run Keycloak or another standard OIDC provider
  • Instead of Lambda, you run functions on Kubernetes with Knative or OpenFaaS

Every one of these speaks an open protocol, SQL, AMQP, CloudEvents, OIDC, rather than a single vendor’s proprietary interface, which is what removes the SDK entanglement problem at the source rather than papering over it.

This is the same conclusion GEICO reached after a decade spent migrating over 600 applications to the public cloud. Its VP of platform and infrastructure engineering, Rebecca Weekly, put it plainly: “Ten years into that journey GEICO still hadn’t migrated everything to the cloud, their bills went up 2.5X and their reliability challenges went up quite a lot too.” Its repatriation runs on an OpenStack and Kubernetes private cloud, and the reasoning its team has given publicly is the same one made here: standard APIs mean the infrastructure doesn’t dictate the application architecture the way a proprietary managed service does.

The honest caveat is that this trades one thing for another. AWS’s managed services are managed for a reason: someone else runs the database, patches the message broker, and handles the auth flows. Running PostgreSQL, Kafka, or Keycloak yourself on OpenMetal means your team owns that operational work, unless you use OpenMetal’s assisted management options, which cover hardware and platform support but not full management of every application-layer service you choose to run.

If your team doesn’t already have that platform engineering experience, this is a real cost to plan for, not just an inconvenience mentioned in passing. For a full accounting of what a migration like this actually takes, timelines included, see The AWS to OpenMetal Migration Playbook.

Visualizing the AWS Lock-In Trap

Deciding What to Untangle First

Not every AWS dependency deserves the same urgency, and treating them all as equally locked-in is its own mistake. A useful way to sequence this:

  • Start with plain compute and storage. EC2, EBS, and S3-equivalent workloads are close to commodity at this point, egress is often waivable if you’re leaving entirely, and there’s no proprietary data model or event format standing in the way. These move first and fastest.
  • Audit the managed services next, and rank them by coupling depth rather than by how much they cost you monthly. A Lambda function with no external triggers is a smaller problem than a Cognito user pool with 200,000 active users. Data model and credential coupling (DynamoDB, Cognito) is generally harder to unwind than message-passing coupling (SQS, SNS, EventBridge), which is harder than compute coupling (Lambda, API Gateway).
  • Budget the hard dependencies in engineer-months, not dollars. A DynamoDB or Cognito migration is a project with a dual-run period, a cutover plan, and real risk if it’s rushed. Treating it like a data transfer task is how migrations blow their timelines.
  • And be honest about which workloads shouldn’t move at all. Genuinely elastic, spiky, or globally distributed workloads are still a legitimate reason to stay on public cloud managed services. This isn’t an argument for abandoning cloud everywhere. It’s an argument for knowing which of your dependencies are actually load-bearing architecture decisions versus which ones were just the path of least resistance five years ago. If you’re trying to figure out where your own workloads fall on that spectrum, A Practical Guide to a Successful Public Cloud Exit Strategy walks through the assessment in more detail.

If you’ve done that audit and found a set of workloads where the managed-service coupling is more habit than requirement, the next step is sizing what a private cloud alternative actually looks like for your specific hardware and workload profile. You can start that with a proof of concept.

FAQ

Is AWS egress still a major lock-in cost?

Less than it used to be. Since March 2024, AWS waives data transfer out to the internet for customers moving all their data off the platform, provided the account qualifies and the transfer completes within a 90-day window. It’s not automatic and doesn’t cover every service, but for a full exit it removes what used to be the headline cost.

Which AWS managed services are hardest to migrate away from?

Cognito and DynamoDB are typically the hardest, because they involve data you can’t cleanly export (password hashes) or a data model that has to be redesigned rather than translated (DynamoDB’s access-pattern-driven schema). Step Functions, EventBridge, SQS, and SNS involve rewriting integration code but not redesigning your core data or credentials.

Does moving off Lambda mean rewriting all my application code?

Usually not the function bodies themselves, those are often portable. What has to be rewritten is everything around them: IAM execution roles, event source mappings, and the AWS-specific payload shapes each trigger delivers.

Is cloud repatriation only about cost?

Cost is the most commonly cited driver, but compliance requirements and the desire for architectural control show up consistently in survey data as well. Most organizations are repatriating specific workloads selectively, not exiting the cloud entirely.

Chat With Our Team

We’re available to answer questions and provide information.

Reach Out

Schedule a Consultation

Get a deeper assessment and discuss your unique requirements.

Schedule Consultation

Try It Out

Take a peek under the hood of our cloud platform or launch a trial.

Trial Options

 

 

 Read More on the OpenMetal Blog

The Real AWS Lock-In Is Managed Services, Not Egress

Jul 13, 2026

We look at why AWS egress fees are no longer the lock-in mechanism people think they are, and walk through the specific managed services (Lambda, DynamoDB, Step Functions, EventBridge, SQS/SNS, Cognito, API Gateway) that actually make leaving AWS hard.

How to Prevent Private Cloud Migration Delays

Jul 08, 2026

Planning a private cloud project? Organizing well from the start can prevent expensive and time-consuming delays. Our guide explains why hosted private cloud projects stall across migration and day two operations and shows how to prevent delays with better planning, architecture, ownership, and operational readiness.

Top 8 Reasons Companies Leave Public Cloud in 2026

Jul 06, 2026

A skimmable breakdown of the main business and technical drivers pushing companies from public cloud to hosted private cloud, covering cost control, compliance, performance, and operational control.

What AI Startups Need to Plan for Before Their Cloud Credits Run Out

Jul 01, 2026

Hyperscaler credits are worth taking, but the architecture built during the subsidized period determines your real cost when billing starts. This covers the credit lifecycle, which decisions create long-term cost exposure, and when private infrastructure makes sense for AI startups in production.

How Nutanix and OpenMetal Compare as VMware Alternatives for Mid-Market IT Teams

Jun 29, 2026

Nutanix is a legitimate VMware alternative with real advantages. But its per-core subscription model has cost implications that compound at scale. This article compares both platforms honestly across pricing, operations, migration tooling, and use case fit.

Why MSPs Should Own Their Cloud Infrastructure Instead of Reselling It

Jun 26, 2026

Azure CSP resale margins are thin and getting thinner as Microsoft shifts incentives away from transaction volume. This article covers the commercial model for MSPs who own their infrastructure instead, how OpenStack multi-tenancy enables per-client isolation on shared hardware, and what the right client segment looks like.

When Running Apache Spark and Delta Lake Without Databricks Makes Financial Sense

Jun 22, 2026

Databricks’ Standard tier is being retired, forcing Premium upgrades with higher DBU rates. This article covers how the DBU billing model works, what the open-source stack underneath Databricks looks like, what you give up by self-managing it, and when private cloud infrastructure changes the economics.

How MSPs Can Win Clients With Compliance and Private Cloud

Apr 30, 2026

Enterprise clients in regulated industries are asking harder infrastructure questions than most MSPs are equipped to answer. This article covers where the Microsoft stack has limits for compliance workloads, what private cloud adds to an MSP’s portfolio, and how to start without overhauling your entire stack.

How US Companies Get EU Infrastructure Without Building EU Operations

Apr 23, 2026

EU expansion means facing data residency questions your US infrastructure can’t easily answer. This guide breaks down what EU customers actually need, why Amsterdam is the right location, how fixed-cost hosted infrastructure compares to hyperscaler EU regions, and what you don’t actually need to build.

Multi-Cloud Disaster Recovery: Building a Hybrid DR Strategy with OpenMetal and AWS or Azure

Apr 22, 2026

Running production and recovery on the same provider creates vendor concentration risk that most DR plans don’t address. This article covers both hybrid DR architectures, how to choose the right direction for your organization, what hyperscaler DR actually costs, and the tooling that makes cross-provider recovery work reliably.