A small web app on AWS moves to Cloud Run as the same container: App Runner and Fargate images run unchanged, and a Lambda function becomes a web server. Cloud Run scales it to zero, so a quiet month costs $0 where Fargate behind a load balancer costs about $47. Move the app and its data together, and stay when the data and permissions live in AWS.
In short
- App Runner has been closed to new customers since April 30, 2026; existing customers keep it, with no new features planned, and its image runs on Cloud Run as it is.
- One small API, 1 million requests of 200 ms and 50 GB out a month: Lambda $1.11, Cloud Run $5.37, Fargate with a load balancer $47.12, ECS Express Mode $64.89.
- 10 million requests that each wait 2 seconds cost $172.90 a month on Lambda and $73.21 on one Cloud Run instance taking up to 80 at once.
- For steady load Fargate is cheaper: $0.04048 per vCPU-hour against $0.0648 on Cloud Run with instance-based billing.
- Cloud Run gives a container 10 seconds after
SIGTERM; ECS gives 30 by default.
Prices are list prices of October 12, 2026, in eu-west-1 and europe-west1, for a 30-day month.
What changed at AWS
AWS closed App Runner, the service closest to Cloud Run, to new customers from April 30, 2026. Its availability page says that existing customers can go on using it, including creating new services, and that AWS keeps investing in its security and availability but does not plan new features. For newcomers it recommends ECS Express Mode.
Express Mode creates a Fargate service from an image and two IAM roles in one call: the task, an Application Load Balancer with TLS, autoscaling and a URL. It costs nothing on top of what it creates. Its defaults are 1 vCPU and 2 GB per task, a minimum of one task and a CPU target of 60%, and the load balancer it creates is shared by up to 25 services with the same network setup. So Express Mode is Fargate made easier to start, with Fargate's bill: one task and one load balancer running all month, busy or idle.
What each piece becomes
The core of the move is one line: the web service, wherever it runs on AWS, becomes a Cloud Run service. The rest of a small app usually maps one to one.
What differs between the three starting points is how much of the app changes:
- From App Runner or Fargate, the container image is the same. Cloud Run runs Linux x86_64 images that listen on the port in the
PORTvariable, 8080 by default, which most App Runner and Fargate images already do. What changes is the settings around it: the task definition or the App Runner configuration becomes flags on one deploy command. - From Lambda, the handler becomes a web server. Lambda calls a function with an event; Cloud Run sends HTTP requests to a server you start. If the function already runs a framework through the Lambda Web Adapter, drop the adapter and start the server directly. If it is a bare handler, a small wrapper turns it into a server; the Lambda guide has one, tested.
Cloud Run itself: one instance takes up to 1,000 requests at once (80 times its vCPUs by default from gcloud), a request can last 60 minutes, the service scales to zero when idle, every service gets an HTTPS address with no load balancer to set up, and Google commits to 99.95% monthly uptime for every service (99.9% in Mexico and Stockholm).
What a small app costs on each side
The fairest comparison is one app on each platform's usual setup. Take a small API: 1 million requests a month of 200 ms each, 50 GB of responses, in Ireland (eu-west-1) on AWS and Belgium (europe-west1) on Google Cloud, at list prices read on October 12, 2026, for a 30-day month.
- Lambda, $1.11. The free tier covers the compute (400,000 GB-seconds) and the requests (1 million); what is left is the HTTP API at $1.11 per million requests. AWS's 100 GB of free internet traffic a month covers the 50 GB.
- Cloud Run, $5.37. The free tier covers the compute; what is left is 46.6 GiB of traffic at $0.105 per GiB, Cloud Run's own price from Europe to Europe, $4.89, plus $0.48 of CPU. This is an upper bound: it assumes no two requests share an instance. Our egress guide explains the $0.105 and the $0.12 on Google's network page.
- Fargate, $47.12. One task of 0.5 vCPU and 1 GB running all month is $17.77; the load balancer is $18.14 for its hours plus about $0.40 of capacity units; three public IPv4 addresses (two for the load balancer, one for the task) are $10.80.
- ECS Express Mode, $64.89. The same, with its default task of 1 vCPU and 2 GB at $35.55. If the load balancer is shared by other services, its share of the bill falls.
So for short requests at this size, Lambda costs least and Cloud Run is a few dollars more, mostly for traffic. The order changes when requests wait. Take 10 million requests a month that each spend 2 seconds waiting on an outside API: Lambda bills every environment for every second it waits, $172.90 a month, while one Cloud Run instance taking up to 80 requests at once and busy all month costs $73.21. The Lambda guide has that model.
For steady load the comparison turns again. A Fargate vCPU-hour is $0.04048; a Cloud Run vCPU-hour on instance-based billing is $0.0648. An app that keeps two tasks busy around the clock costs less on Fargate, and Savings Plans widen the gap; the ECS guide works through it. A quiet month is where Cloud Run's model pays: the Fargate app above costs $46.72 with no traffic at all, and the Cloud Run service costs $0.
App Runner sits between the two for its existing customers: a provisioned instance of 1 vCPU and 2 GB is billed $0.007 per GB-hour for memory while idle, $10.08 a month, plus the active vCPU and memory while it serves.
When staying is the better call
- The data lives in AWS. A large RDS database, S3 buckets that other systems write and read, a data warehouse fed from them. An app on Cloud Run that calls a database in AWS crosses the internet on every query, which adds latency and egress charges on both sides. Move the app and the data together, or not at all.
- Permissions are shared. IAM roles used by several services, KMS keys, VPC peering with other teams. Rebuilding them is work that pays only if most of it moves.
- The first request after a quiet spell must answer in 0.3 s. Lambda started a stopped function faster than Cloud Run in the TU Berlin study: 0.28 to 0.31 s against 0.53 s at the median. Our cold start guide has the numbers and what a minimum instance costs to remove the wait.
- The load is steady and large. As above, Fargate with a Savings Plan costs less per vCPU-hour than Cloud Run.
- The event wiring is deep. Dozens of SQS queues, SNS topics, Step Functions and EventBridge rules each have a counterpart on Google Cloud, but each is its own small move.
The move, step by step
1. Read what runs
Before changing anything, list what the app uses. These are read-only:
aws apprunner list-services
aws ecs list-services \
--cluster default
aws ecs describe-task-definition \
--task-definition orders-api
aws lambda list-functions \
--query 'Functions[].[FunctionName,Runtime,MemorySize,Timeout]'
aws rds describe-db-instances \
--query 'DBInstances[].[DBInstanceIdentifier,Engine,EngineVersion,DBInstanceClass]'Note the memory and CPU, the port, the environment variables and which of them come from Secrets Manager or Parameter Store, the schedules, the queues, the buckets and the database engine and version.
2. Run the image the way Cloud Run will
Cloud Run's contract is short: listen on 0.0.0.0 at the port in PORT, treat the disk as memory that goes away, and finish within 10 seconds of a SIGTERM. Check all three on your machine before you deploy:
docker build -t orders-api .
docker run -d --name orders-api -e PORT=8080 -p 8080:8080 orders-api
curl -s localhost:8080/orders/42
time docker stop orders-apiOur sample App Runner app answered {"id":"42","state":"paid"} and stopped in 0.27 s with exit code 0, because its server closes on SIGTERM. ECS gives a container 30 seconds by default and up to 120; Cloud Run gives 10, then kills it. If your images are built for Graviton (ARM, about 20% cheaper on Fargate), build an x86_64 one for Cloud Run:
docker buildx build \
--platform linux/amd64 \
-t orders-api .3. Copy the secrets
Each value goes from Secrets Manager to Secret Manager through a pipe, so it never lands on a command line or in a file:
aws secretsmanager get-secret-value \
--secret-id orders-db \
--query SecretString \
--output text |
gcloud secrets create orders-db \
--data-file=-If the secret holds JSON with several keys, split it into one secret per key first. Our secrets guide covers access and rotation.
4. Copy the data
- Postgres or MySQL on RDS moves to Cloud SQL. For a small database, a dump and a restore during a short maintenance window is enough; our Postgres guide has the commands and the row-count check. For a larger one, Google's Database Migration Service copies it and then streams changes until you switch, at no extra charge for Postgres to Postgres and MySQL to MySQL. On RDS it needs
rds.logical_replicationset to 1, thepglogicalextension and therds_replicationrole for its user, and the parameter change restarts the instance. - S3 copies to Cloud Storage with Storage Transfer Service, which costs nothing on Google's side for this kind of transfer; AWS bills the data going out at its internet rates. The code that calls S3 changes to the Cloud Storage client, as in our files guide.
5. Deploy and test
Push the image to Artifact Registry and deploy it with the settings you listed in step 1, as flags:
gcloud artifacts repositories create apps \
--repository-format=docker \
--location=europe-west1
gcloud auth configure-docker europe-west1-docker.pkg.dev
docker tag orders-api europe-west1-docker.pkg.dev/PROJECT/apps/orders-api:1
docker push europe-west1-docker.pkg.dev/PROJECT/apps/orders-api:1
gcloud run deploy orders-api \
--image=europe-west1-docker.pkg.dev/PROJECT/apps/orders-api:1 \
--region=europe-west1 \
--service-account=orders-api@PROJECT.iam.gserviceaccount.com \
--set-secrets=DATABASE_URL=orders-db:latest \
--add-cloudsql-instances=PROJECT:europe-west1:orders \
--allow-unauthenticatedTest it on the run.app address Cloud Run prints, with the copied data, before any user sees it. The service account replaces the IAM role the task or function had: grant it exactly what the app needs, as our IAM guide shows.
6. Switch the domain
Lower the DNS record's TTL a day ahead, freeze writes on the AWS side if the data was copied once, copy the last changes, compare row counts, and point the record at Cloud Run. Keep the AWS service running, scaled down, for a week as the way back. Our cutover checklist has the order hour by hour.
What breaks most often
- ARM images. An image built only for arm64 does not start on Cloud Run. Build for linux/amd64, or a multi-arch image that includes it.
- Shutdown time. Code that relies on ECS's 30 seconds to drain loses work after Cloud Run's 10. Finish quickly, or hand long work to a queue.
- The disk. Fargate gives a task 20 GB of ephemeral storage; on Cloud Run the file system lives in the instance's memory and counts against its limit.
- Credentials. The AWS SDK finds its role through the task or function environment. On Cloud Run, Google's client libraries find the service account the same way, with no key file; any leftover AWS calls fail until they are replaced or given credentials.
- Request size. Lambda caps a synchronous request and response at 6 MB; Cloud Run's HTTP/1 request limit is 32 MiB. Code that worked around Lambda's limit can be simplified, but nothing breaks.
- A database left behind. An app moved to Cloud Run while its database stays in RDS gets slower on every query. Move them together.
Where Exodus comes in
exodus audit reads the repository on your machine and lists what it finds. On our sample App Runner app it found the web process from the Dockerfile and Postgres from the dependencies, and the offline report said the app can move as it is, with $10.00 a month on Cloud Run: the service within the free tier, a db-f1-micro Cloud SQL instance at $9.37, $0.03 for stored images and $0.60 of traffic at its default of 5 GB.
Exodus 0.1.3 does not read apprunner.yaml, ECS task definitions or Lambda configuration: the platform shows as Unknown. It did not list the S3 bucket the app writes to, and it counted the database URL as a plain variable although App Runner takes it from Secrets Manager. Your coding agent fills those in from the AWS commands in step 1 and records them with exodus answer, and the plan then puts the steps above in order with the cost on the Google side.
FAQ
Is AWS App Runner being shut down?
App Runner is closed to new customers since April 30, 2026. Existing customers can go on using it, including creating new services, and AWS keeps up its security and availability but plans no new features. For newcomers AWS recommends ECS Express Mode, which is Fargate with a load balancer.
Is Cloud Run cheaper than ECS on Fargate?
For a small or quiet app, yes: a Fargate task with a load balancer costs about $47 a month with no traffic at all, and Cloud Run $0. For load that keeps two tasks busy around the clock, Fargate costs less per vCPU-hour, and Savings Plans widen the gap.
Does Cloud Run run ARM images built for Graviton?
No. Cloud Run runs Linux x86_64 images, and an image built only for arm64 does not start. Build for linux/amd64 with docker buildx build --platform linux/amd64, or a multi-arch image that includes it.
How do I move an RDS Postgres database to Cloud SQL?
A small database moves with a dump and a restore during a short maintenance window. For a larger one, Database Migration Service copies the data and streams changes until you switch, at no extra charge for Postgres to Postgres. On RDS it needs logical replication on, which restarts the instance.
How do I copy S3 buckets to Cloud Storage?
Storage Transfer Service copies them and costs nothing on Google's side for this kind of transfer; AWS bills the data going out at its internet rates. The code that calls S3 then changes to the Cloud Storage client.
Sources
26
- docs.aws.amazon.comAWS App Runner availability change, AWS docs
- aws.amazon.comAWS Service Availability Updates, AWS What's New, March 2026
- aws.amazon.comAWS App Runner pricing and its eu-west-1 price list
- docs.aws.amazon.comAmazon ECS Express Mode overview, AWS docs
- docs.aws.amazon.comResources created by Amazon ECS Express Mode services, AWS docs
- aws.amazon.comBuild production-ready applications using Amazon ECS Express Mode, AWS News blog, Nov 21, 2025
- docs.aws.amazon.comUnderstanding Lambda function scaling, AWS docs
- docs.aws.amazon.comLambda quotas, AWS docs
- github.comAWS Lambda Web Adapter, GitHub aws/aws-lambda-web-adapter
- pricing.us-east-1.amazonaws.comAWS price list files for eu-west-1: AWSLambda
- aws.amazon.comAWS Fargate pricing
- docs.aws.amazon.comAmazon ECS task definition parameters, AWS docs
- aws.amazon.comAWS data transfer price list for eu-west-1
- aws.amazon.comAWS Lambda pricing
- cloud.google.comCloud Run pricing, Google
- docs.cloud.google.comMaximum concurrent requests for services, Cloud Run docs, Google
- docs.cloud.google.comCloud Run quotas and limits, Google
- cloud.google.comCloud Run SLA, Google
- docs.cloud.google.comContainer runtime contract, Cloud Run docs, Google
- docs.cloud.google.comCompare AWS and Azure services to Google Cloud, Google
- docs.cloud.google.comConfigure your source for PostgreSQL, Database Migration Service docs, Google
- cloud.google.comDatabase Migration Service pricing, Google
- docs.cloud.google.comTransfer from Amazon S3 to Cloud Storage, Storage Transfer Service docs, Google
- cloud.google.comStorage Transfer Service pricing, Google
- docs.cloud.google.comConfigure secrets for services, Cloud Run docs, Google
- Exodus team: exodus 0.1.3 audit and report on a sample App Runner app