compute

AWS App Runner

Run a containerized web app or API from source code or an image, with the load balancer, scaling, and HTTPS handled for you. Here's where App Runner sits between Lambda and ECS, what it costs, and the mistakes Design Beaver catches as you draw.

Updated September 6, 2026

What App Runner is

App Runner runs web applications and HTTP APIs for you. You hand it either a source repository or a container image, and it does the rest — building the image when it’s source code, deploying it, putting a load balancer in front, scaling instances with traffic, and terminating HTTPS on a default *.awsapprunner.com URL.

It’s the middle of the AWS compute spectrum. Lambda is built for short event-driven bursts and doesn’t suit a continuously-running web app. ECS and Fargate give you full control but make you assemble load balancers, target groups, scaling policies, and networking yourself. App Runner is the “I just want my web app online” option that hides all of that.

Design Beaver models App Runner as a managed service with its own endpoint, outside your subnets unless a VPC connector attaches it, and validates as you draw which edges are real and what each one needs.

When to use App Runner (and when not to)

Reach for App Runner when the app is a containerizable HTTP service and you want it deployed and auto-scaled with minimal configuration. Push-to-deploy from GitHub, or point it at a prebuilt ECR image and skip the build pipeline entirely. It suits request/response traffic that benefits from staying warm, and it means not owning load balancers, scaling policies, or OS patching.

Don’t reach for it when you need fine-grained control over networking, the load balancer, task placement, or sidecar containers — that’s the moment you’ve outgrown it and ECS/Fargate is the answer. It’s also wrong for non-HTTP workloads: queue workers, batch jobs, and gRPC-only or raw TCP services don’t fit a single HTTP port with a health check. And for very spiky handlers that are idle most of the time, paying for warm provisioned capacity is waste — Lambda bills closer to zero when nothing’s happening.

Variants: how App Runner gets your app

The source type is the real decision. It changes whether you own a build pipeline, and it changes your bill.

OptionWhat it is
Source code (automatic build)defaultPoint App Runner at a source directory in a GitHub (or Bitbucket) repository and pick a managed runtime; App Runner builds a container image from your code and the runtime base image, then deploys it. With automatic deployment on, commits to the source directory trigger a new build and deploy.
Source image (container image)Point App Runner at a prebuilt container image in a repository (typically a private Amazon ECR repo, or ECR Public). No build stage — App Runner runs the image directly. Automatic deployment is supported for private ECR images but not for ECR Public.

One asymmetry worth knowing before you pick: automatic redeploy on a new image works for private ECR repositories, but not for ECR Public.

App Runner pricing in plain English

You pay two different ways at once: warm memory to stay ready, and vCPU compute while requests are actually in flight.

Pay for the compute and memory your service uses. Provisioned (idle/warm) container instances are billed for memory only, keeping the app warm to avoid cold starts. Active container instances (while handling requests) are billed for vCPU compute plus any memory used beyond the provisioned amount. All usage is billed per second, rounded up. Source-code builds also incur a small build/automation charge.

OptionRepresentative rate
source-imageProvisioned memory ~$0.007 / GB-hour; active compute ~$0.064 / vCPU-hour (plus active memory in excess of provisioned)
source-codeSame compute/memory rates as source-image, plus ~$0.005 per build-minute when App Runner builds the image from source, and a fixed monthly automation fee per service if automatic deployments are enabled.

Keeping the bill down

  • Set a sensible minimum-size / minimum-provisioned configuration so you aren't keeping more warm capacity than the traffic pattern needs
  • If the workload is genuinely spiky and often idle, compare against Lambda — App Runner bills for warm provisioned memory even when no requests arrive
  • Right-size the per-instance CPU/memory to the app rather than over-provisioning

us-east-1 (rates vary by region). Rates as of 2026-09. Verify at the official pricing page before using for real cost estimates — this list is not kept in sync with AWS pricing changes.

That split is the whole cost story. Provisioned instances bill for memory even at zero traffic, which is what buys you no cold starts. It also means an idle App Runner service costs real money, unlike an idle Lambda.

How App Runner connects to other services

Two things decide whether an App Runner architecture works: which of its two roles carries a permission, and whether it has a path into your VPC at all.

  • RDS

    The App Runner application connects to a private RDS database (e.g. PostgreSQL) as its data layer, reaching it over the VPC through a VPC connector

  • ECR

    App Runner deploys a source-image service from a private container image stored in Amazon ECR

  • S3security

    The App Runner application reads/writes S3 objects via the AWS SDK (e.g. serving or storing user uploads, reading config/assets, writing logs)

    IAM:s3:GetObjects3:PutObjects3:ListBucket

  • DynamoDBsecurity

    The App Runner application reads/writes DynamoDB items via the AWS SDK (typical web-API backend pattern)

    IAM:dynamodb:GetItemdynamodb:PutItemdynamodb:Querydynamodb:UpdateItemdynamodb:DeleteItem

  • A Route 53 record points a custom domain (root or subdomain) at the App Runner service, which otherwise answers on its default *.awsapprunner.com URL

  • Secrets Managersecurity

    The App Runner application reads a secret (e.g. database credentials or a third-party API key) from Secrets Manager at runtime via the AWS SDK instead of hardcoding it — App Runner can also reference a secret directly in the service's runtime environment configuration

    IAM:secretsmanager:GetSecretValuesecretsmanager:DescribeSecret

The roles run at different times and belong to different owners:

  • The access role pulls your image from private ECR. It trusts build.apprunner.amazonaws.com. It says nothing about runtime permissions.
  • The instance role is what your application code uses to call S3, DynamoDB, and the rest through the SDK. It trusts tasks.apprunner.amazonaws.com. Grant it the actions your code needs and let the SDK pick up rotating temporary credentials — never bake access keys into the image.

For a custom domain, associate it with the service and create a Route 53 ALIAS record pointing at the App Runner application in that region. ALIAS works for root domains and subdomains alike and avoids extra Route 53 query charges. If Route 53 is your DNS provider, App Runner can create the certificate validation records itself.

What App Runner can’t connect to

App Runner’s managed simplicity is also a boundary. These two edges look plausible and don’t exist.

  • App Runner has its own built-in, fully managed load balancer and public HTTPS endpoint — you don't put an Application Load Balancer in front of it, and App Runner isn't a registrable ALB target (ALB targets are instances, IPs, or Lambda functions, not a managed App Runner service). For workloads that need to sit behind your own ALB, use ECS/Fargate instead.

  • ECS

    Peer compute options, not an architectural edge — ECS/Fargate is the service you graduate to when you outgrow App Runner's managed simplicity and need control over networking, the load balancer, or task placement. An app runs on one or the other; they don't connect to each other.

Anti-patterns Design Beaver catches

Each of these is App Runner being used slightly outside the shape it was built for — one breaks, two just cost money.

Reaching for App Runner for a non-HTTP workload (queue worker, batch job, raw TCP/gRPC-only service)

Why it breaksApp Runner is built around a single HTTP request/response port with an HTTP health check; workloads that aren't HTTP request/response don't fit its model

Do this insteadRun non-HTTP workloads on ECS/Fargate, or use Lambda (with SQS/EventBridge) for event-driven processing

Baking long-lived AWS access keys into the container image so the app can call S3/DynamoDB

Why it breaksLong-lived keys in an image are a standing credential-leak risk and defeat automatic rotation

Do this insteadAttach an App Runner instance role and let the SDK pick up automatically-rotated temporary credentials

Keeping a large minimum provisioned size for a service that is idle most of the time

Why it breaksProvisioned (warm) instances are billed for memory even with no traffic, so oversized warm capacity wastes money on idle

Do this insteadLower the minimum size/provisioned configuration, or move genuinely spiky idle-heavy workloads to Lambda

Gotchas that bite in production

  • It isn’t in your VPC by default. Outbound access to private resources needs a VPC connector. Forgetting it is the usual reason the app can’t reach the database.
  • Two roles, two jobs. The access role pulls the image; the instance role is for your app’s AWS calls. Permissions on the wrong one silently do nothing.
  • Warm capacity isn’t free. Provisioned instances bill for memory with no requests arriving. That’s the trade for no cold starts, but budget for it.
  • HTTP only. One request/response port with a health check. Non-HTTP work belongs on ECS/Fargate or Lambda.
  • ECR Public doesn’t auto-deploy. Redeploy-on-push is a private-ECR feature only.

Further reading

Frequently asked questions

When should you use AWS App Runner?
Use App Runner when you have a containerizable web app or HTTP API you want online continuously with as little infrastructure work as possible — git-push-to-deploy from GitHub, or a direct deploy from a prebuilt ECR image. It fits request/response workloads that benefit from staying warm. Move to ECS/Fargate when you need control over networking, the load balancer, task placement, or sidecars. Use Lambda instead for very spiky, mostly-idle event handlers, and for anything that isn't HTTP.
Why can't my App Runner service reach my RDS database?
Because App Runner isn't inside your VPC by default. To reach a private RDS instance you create a VPC connector — a VPC, private subnets, and optionally security groups — and attach it to the service. Then the RDS security group needs an inbound rule allowing the VPC connector's security group on the database port. Without the connector, App Runner simply can't see a private database, and this is the most common App Runner networking failure.
What is the difference between the App Runner access role and instance role?
The access role lets App Runner pull your image from private ECR. It trusts build.apprunner.amazonaws.com and usually carries the AWSAppRunnerServicePolicyForECRAccess managed policy. It has nothing to do with what your app can do once it's running. The instance role is what your application code uses to call S3, DynamoDB, and other AWS APIs through the SDK; it trusts tasks.apprunner.amazonaws.com. Granting S3 permissions on the access role won't help your running app.
How much does AWS App Runner cost?
Provisioned (warm) instances are billed for memory only, which keeps the app warm and avoids cold starts even at zero traffic. Active instances — while actually handling requests — add vCPU compute on top, plus any memory beyond what's provisioned. Everything bills per second, rounded up. Source-code services also pay per build-minute when App Runner builds the image, plus a fixed monthly automation fee per service if automatic deployments are on; deploying a prebuilt ECR image avoids both. In practice that means an idle App Runner service isn't free the way an idle Lambda is. Verify current rates on the official pricing page before estimating a real bill.
Can you put an Application Load Balancer in front of App Runner?
No. App Runner already has its own managed load balancer and public HTTPS endpoint, and it isn't a registrable ALB target — ALB targets are instances, IPs, or Lambda functions. If you need your app behind your own ALB, that's the signal you've outgrown App Runner and should move to ECS/Fargate. Design Beaver flags the ALB → App Runner edge as invalid.

Validate your App Runner architecture as you draw

Design Beaver checks your AWS design in real time — missing queues, invalid connections, and security anti-patterns, caught before you ship. It’s live in beta, free, and runs in your browser. Sign in with Google or GitHub to save your work.

Sign up for free! →

Prefer email? Get new features in your inbox:

Get new features in your inbox

No spam — product updates only, and you can unsubscribe from any email.

← All supported services