
Google App EngineAuthorCloudBrum editorial teamLast reviewedReading time~12 minLevelBeginner to advanced
Google Cloud · App modernization · Platform for web apps
Google’s original platform for web apps: you write the code, it runs the servers. You describe the app in an app.yaml file, deploy with one command, and App Engine runs it on instances it creates, patches and scales. There are two environments, and the choice shapes everything else. The standard environment runs your code in a sandbox, starts in seconds and can scale to zero. The flexible environment runs a Docker container on virtual machines, supports any language, and always keeps at least one instance. A project gets one App Engine app, and its region can’t be changed afterwards, so pick the region on purpose.
On this page (17 sections)
Mind map: Google App Engine at a glance
Free to share. The downloaded image includes the CloudBrum link.
Key features (summary)
- Deploy with one commandDescribe the runtime, the entry point and the scaling in app.yaml, run gcloud app deploy, and App Engine builds, uploads and starts the app. There are no servers or load balancers to create.
- A sandboxed standard environmentThe standard environment runs your code on supported runtimes such as Python, Java, Go, Node.js, PHP and Ruby in a sandbox. Instances start in seconds, and an idle app can drop to zero instances.
- Flexible when you need DockerThe flexible environment runs your container on Compute Engine virtual machines, so any language or library works. In return it’s slower to start and deploy, and it always keeps at least one instance.
- Services and versionsOne app is split into services, such as a web front end and an API, and every deployment creates a version. Several versions can run at once.
- Traffic splittingSend a share of requests to a new version by IP address, cookie or at random, watch it, and shift the rest, or roll back by moving the split.
- Scaling you describeAutomatic scaling adds and removes instances based on CPU, throughput and latency targets you set. Basic and manual scaling give you fixed or request-driven instances for long-running work.
- Access controlsA firewall in front of the app allows or blocks IP ranges, Identity-Aware Proxy puts sign-in in front of it, and a service account decides what the code may do in Google Cloud.
- Friendly with other Google servicesCloud Tasks queues background work, Cloud Scheduler runs cron jobs, Firestore stores data and Cloud Logging and Error Reporting collect what the app emits.
Basic concepts
- App Engine application
- The one App Engine app in a project. It’s created once, in a region you can’t change, and holds all the services.
- Service
- A part of the app with its own code and configuration, for example default and api. Services scale and deploy independently.
- Version
- One deployed snapshot of a service. A service can have many versions, and traffic is split between them.
- Instance
- One running copy of a version. App Engine starts and stops instances as load changes.
- Standard environment
- The sandboxed environment for supported runtimes, with fast start-up, scale to zero and a free daily allowance.
- Flexible environment
- The environment that runs a Docker container on Compute Engine VMs, with any runtime and a minimum of one instance.
- app.yaml
- The file that names the runtime, the entry point, the instance class, scaling settings, environment variables and handlers for a service.
- Instance class
- The size of a standard instance, such as F2 for automatic scaling or B2 for basic scaling, which sets memory and CPU.
- Automatic scaling
- Scaling that follows targets for CPU, throughput and latency, with limits on minimum, idle and maximum instances.
- Traffic splitting
- A setting that divides requests among versions by IP address, cookie or randomly, used for canary releases and A/B tests.
- dispatch.yaml
- A routing file that sends requests to services by URL pattern.
- Cloud Tasks and Cloud Scheduler
- The services that replaced the older task queue and cron.yaml features, for background work and scheduled calls.
- Serverless VPC Access
- A connector that lets an app reach resources in your VPC network, such as a private database.
- Identity-Aware Proxy
- A Google service that requires sign-in and an IAM role before a request reaches your app.
How to create & configure it
Deploy an app with gcloud
- Choose the project and the regionUse a project with billing. The App Engine region is fixed for the life of the project, so choose one near your users and data, such as asia-south1 (Mumbai).
- Create the app and the service accountRun gcloud app create with the region. Make a service account for the app with only the roles it needs, and use it instead of the default one.
- Write app.yamlName the runtime, the entry point (for example gunicorn for Python), the instance class, the scaling limits, environment variables and HTTPS-only handlers.
- Connect it to your network if neededIf the app talks to private resources, create a Serverless VPC Access connector and name it in app.yaml, with an egress setting that sends only private ranges through it.
- Deploy without promotingDeploy with --no-promote and a clear version name. The new version runs, but traffic stays on the old one.
- Test and split the trafficOpen the version’s own URL, then send a small share of requests to it with set-traffic. Watch errors and latency before moving the rest.
- Add schedules and a firewallCreate Cloud Scheduler jobs that call your handlers, and set firewall rules so that only the sources you expect can reach the app.
- Protect the front doorTurn on Identity-Aware Proxy for internal apps, or put a load balancer with Cloud Armor in front of public ones.
- Keep the version list tidyDelete old versions that no longer receive traffic. They cost nothing while stopped, but the list and the version limit grow.
Tip: for a first deployment, gcloud app deploy from your project folder is enough. For anything shared, keep app.yaml in Git and the project settings in Terraform (see the code references). Also look at Cloud Run before you start, since many teams now begin new web services there.
Common issues after configuration
| Symptom | Likely cause | What to check / fix |
|---|---|---|
| Error 500 Server Error right after deployment | The app crashed at start-up, the entry point is wrong, or a dependency is missing | Read the logs in Cloud Logging, check the entrypoint in app.yaml and the requirements.txt or package.json, and test the same command locally. |
| The app is not listening on the port or health checks fail (flexible) | The container doesn’t listen on 8080, or it starts too slowly for the health check | Listen on $PORT (8080 by default), tune the readiness and liveness checks, and raise the start-up time allowed. |
| Permission denied calling Google APIs from the app | The app runs as a service account without the needed role | Check the service account in app.yaml or the app settings, grant the role and wait a minute for IAM to catch up. |
| Requests are slow after a quiet period | The standard environment scaled to zero, so a request waits for a new instance | Set min_idle_instances to a small number, keep the app’s start-up work light and use warmup requests. |
| The bill grew although traffic did not | Idle instances, a high minimum or flexible instances that can’t scale to zero keep billing | Review min_instances and min_idle_instances, use standard where it fits, and stop versions you don’t use. |
| DeadlineExceededError or a 504 on long requests | The request ran past its deadline, which depends on the scaling type and runtime | Keep requests short, move the work to Cloud Tasks or a background job, and use basic or manual scaling only for work that really needs a longer deadline. |
| Traffic split settings are rejected | The split must add up to 1.0, and the versions must be serving | Check that fractions sum to one, that the versions exist and that you picked a valid --split-by value. |
| Can’t reach a private database | No VPC connector, or its egress setting doesn’t send the traffic into the VPC | Create a Serverless VPC Access connector in the same region, name it in app.yaml and allow the connector’s range in the firewall. |
| Too many versions error when deploying | App Engine limits the number of versions per app | List versions, delete the ones that aren’t receiving traffic and consider a cleanup step in your pipeline. |
| gcloud app create fails because the app already exists | A project can only have one App Engine app, and it was created earlier | Use the existing app. Its region can’t be changed, so a different region means a new project. |
| Cron jobs don’t run | The scheduler job has the wrong URL or service, or the handler requires a login | Check the job’s target, the service and the HTTP method, and allow the scheduler’s requests in your handler or IAP settings. |
Use cases: when and where to use it
Good fit
- Web apps and APIs in a supported runtime where you want to deploy with app.yaml and no infrastructure
- Apps with spiky or low traffic, which can scale to zero on the standard environment
- Back ends for mobile and web apps that use Firestore, Cloud Tasks and other Google services
- Existing App Engine apps that your team already knows and runs
- Internal tools behind Identity-Aware Proxy
- Apps made of a few services that you deploy and split traffic for separately
Consider something else
- Containers with any language and scale to zero → Cloud Run
- Small event-driven functions → Cloud Run functions
- Full Kubernetes → Google Kubernetes Engine
- A server with its own operating system → Compute Engine
- The same job on other clouds → compare Azure App Service and AWS Elastic Beanstalk
Pros: why consider it?
Why teams choose it
- Deploy with one command and no infrastructure to design
- Scale to zero and a free daily allowance on the standard environment
- Services, versions and traffic splitting built in
- Tight links with Cloud Tasks, Cloud Scheduler, Firestore and logging
- IAP and firewall rules in front of the app
- Flexible environment for Docker when the sandbox is too limiting
Trade-offs to weigh
- One app per project, and the region can never change
- The standard sandbox limits runtimes and system access, and custom Docker images aren’t supported there
- Flexible always runs at least one instance and starts and deploys slowly
- Less control than Cloud Run or Kubernetes over networking and scheduling
- Many teams now prefer Cloud Run for new services, so examples and community energy lean that way
- Some older bundled services are gone or replaced, which matters when you read old tutorials
Common threats, vulnerabilities & risks
| Risk | Severity | Why it matters | Mitigation |
|---|---|---|---|
| Running as the default App Engine service account | High | That account often has broad project rights, which a compromised app inherits. | Create a dedicated service account with minimal roles and name it in app.yaml. |
| A public app with no protection | High | Anyone can hit the app, including scanners and abusive clients. | Use firewall rules, IAP for internal apps, and a load balancer with Cloud Armor for public ones. |
| Choosing the wrong region | High | The region is permanent for the project, so a mistake means a new project and a migration. | Decide on the region with data location and latency in mind before creating the app. |
| Secrets in app.yaml or Git | Medium | Environment variables in the file are visible to anyone with access to the repository. | Read secrets from Secret Manager at start-up, using the service account. |
| No maximum instance setting | Medium | A spike or a bug can scale instances, and the bill, and overload the database behind them. | Set max_instances, and use connection pooling for the database. |
| Flexible environment kept for simple apps | Medium | You pay for always-on virtual machines and slower deploys when standard would do. | Use standard where the runtime fits, or move the container to Cloud Run. |
| Old versions piling up | Low–Med | The version list grows and the limit is reached at an inconvenient time. | Delete versions with no traffic in your pipeline. |
| Outdated runtime | Low–Med | Retired runtimes lose security fixes and may stop deploying. | Track runtime support dates and upgrade on a version with no traffic first. |
| Dependence on legacy bundled services | Low–Med | Old code that uses removed or replaced APIs breaks when the runtime changes. | Move to Cloud Tasks, Cloud Scheduler, Firestore and Memorystore as part of the upgrade. |
Performance optimisation
- Pick the instance class from measurements: a bigger class gives more CPU and memory per instance, and handles more concurrent requests.
- Set min_idle_instances to a small number for user-facing services, so a quiet period doesn’t mean a cold start for the next visitor.
- Tune target_cpu_utilization and max_concurrent_requests by load testing. Lower targets scale earlier at higher cost.
- Keep start-up work light: lazy initialisation, small dependency sets and warmup handlers.
- Serve static files through App Engine’s static handlers or Cloud CDN and keep instances for dynamic work.
- Keep the app and its data in the same region, and use connection pooling for databases.
- Move slow and background work to Cloud Tasks, which has retries and rate limits, instead of making users wait.
- Check latency percentiles in Cloud Monitoring and Trace after each deployment, not just averages.
Reduce monthly cost
FinOps is the habit of managing cloud spend together with engineering. These are the FinOps checks that matter most for Google App Engine.
- Know your meter: instance hours by class on the standard environment, and vCPU, memory and disk on flexible.
- Use the free daily allowance of standard instance hours for small apps and test services. Sources disagree on the exact hours, so read Google’s page.
- Let services scale to zero where a cold start is acceptable, and keep idle instances only where users would notice.
- Set max_instances so a spike or a bug can’t scale the bill without limit.
- Choose the smallest instance class that handles your concurrency, and raise concurrency where the code allows.
- Prefer standard over flexible where the runtime fits, since flexible always bills for at least one instance.
- Stop or delete old versions and unused services, and remember that flexible versions bill while running.
- Watch data egress, Firestore operations and logging, which can grow faster than instance hours.
- Use committed use discounts where they apply to flexible’s underlying resources.
- Label the project by team, export billing to BigQuery and set budget alerts.
Instance prices, the free daily allowance and flexible rates come from Google's pricing page and secondary sources as we read them in October 2026, and they differ by region and change over time. Check the live page before you plan around them (see Pricing).
Security optimisation
- Run the app as a dedicated service account with minimal roles, never the default one.
- Use IAP for internal apps, so a Google sign-in and an IAM role are needed to reach them.
- Set firewall rules that allow only expected source ranges, and put a load balancer with Cloud Armor in front of public apps.
- Serve everything over HTTPS with secure: always handlers, and use Google-managed certificates for custom domains.
- Keep secrets in Secret Manager and read them at start-up, and keep them out of app.yaml and Git.
- Use a Serverless VPC Access connector or Direct VPC egress with firewall rules for private resources, and send only private ranges through it.
- Validate input and authentication inside the app as well, since the platform can’t know your business rules.
- Turn on Cloud Audit Logs and alert on IAM changes for the project and on unusual error rates.
- Control who can deploy and delete versions with IAM roles such as App Engine Deployer, and keep App Engine Admin for few people.
- Scan dependencies in your pipeline, and upgrade runtimes before they reach end of support.
Governance & compliance
Guardrails
- Labels on the project and its resources (owner, environment, cost centre) enforced through Terraform modules and organisation policy
- An organisation policy that restricts allowed locations, so the permanent App Engine region is chosen from an approved list
- A shared Terraform module for App Engine apps, with a dedicated service account, firewall rules and IAP already set
- A list of approved runtimes with a support end date for each, and an owner for every service that still runs on an old one
Continuous checks (organisation policy and Security Command Center)
- The gcp.resourceLocations constraint, which limits where an App Engine region may be chosen
- A Security Command Center finding for services reachable from the whole internet
- A check for App Engine versions that run as the default service account
- A check for handlers that allow HTTP instead of secure: always
- An alert on the number of versions per service nearing the limit
Cloud Audit Logs record who deployed, changed or deleted versions and services, organisation policy limits where and how projects may be created, Security Command Center reports findings, and the Compliance resource center holds Google’s certificates. Google runs the platform, the instances and the scaling, while you own the code, the service account, the firewall and IAP settings, the region choice and the runtime upgrades.
Reduce carbon footprint
- Scale to zero for apps that are idle much of the day.
- Right-size the instance class and raise concurrency where the code allows.
- Prefer the standard environment, which uses no always-on virtual machine.
- Delete unused versions, services and test projects.
- Choose a region with a high carbon-free energy share when data rules allow. Google publishes the percentage for each region, and the App Engine region can’t be changed later.
- Cache and compress responses, so fewer requests reach instances.
- Cloud Carbon Footprint in the console estimates emissions per project and service. Check what it shows for App Engine before you quote a figure.
Pricing
Purchase options
Standard environment Per instance-hour
Billed by instance class while instances run, with a free daily allowance of instance hours. An app that scales to zero pays nothing for idle time.
Flexible environment Per vCPU, GB of memory and disk
Billed for the resources of the virtual machines that run your containers, for as long as they run, with at least one instance always up.
Free quota Per day
Standard has a free daily allowance. Sources give different numbers of free instance hours by class, so check Google’s page.
Everything around it Varies
Network egress, Firestore or Datastore operations and storage, Cloud Tasks, logging and monitoring, Memorystore and load balancers or Cloud Armor in front.
What you actually pay for
- Instance hours of the standard environment, minus the daily free allowance
- vCPU, memory and disk of flexible instances while they run
- Data stored and operations in Firestore or Datastore
- Network egress, logging and monitoring
- Load balancers, Cloud Armor, VPC connectors and any other service in front of or behind the app
Rates differ by region and instance class and can change. See the official App Engine pricing page, the Google Cloud Pricing Calculator and Google's comparison of the standard and flexible environments.
Important code references
The orders-api app in the App Engine standard environment: a dedicated service account, automatic scaling with one idle instance, HTTPS-only handlers, a VPC connector for private traffic, a firewall and a nightly Cloud Scheduler job. The gcloud tab deploys a new version without traffic and splits 10% of requests to it. Terraform builds the app and a version. The Python tab deletes old versions that get no traffic, and the C# tab lists versions with their traffic share. Replace the project, bucket and connector with your own. The region can’t be changed once the app exists, so check it before you run the first command.
# Placeholders: replace the project, bucket and connector range with your own.
PROJECT=my-orders-project
REGION=asia-south1
BUCKET=orders-receipts-example
SA=orders-api@$PROJECT.iam.gserviceaccount.com
gcloud config set project $PROJECT
gcloud services enable appengine.googleapis.com cloudbuild.googleapis.com vpcaccess.googleapis.com cloudscheduler.googleapis.com
# One narrow service account for the app. The region you pick here is permanent for the project.
gcloud iam service-accounts create orders-api --display-name="orders-api"
gcloud storage buckets add-iam-policy-binding gs://$BUCKET --member="serviceAccount:$SA" --role=roles/storage.objectCreator
gcloud app create --region=$REGION --service-account=$SA
# A connector so the app can reach private addresses in the VPC.
gcloud compute networks vpc-access connectors create orders-conn --region=$REGION --network=orders-net --range=10.8.0.0/28
cat > app.yaml <<EOF
runtime: python313
entrypoint: gunicorn -b :\$PORT -w 2 main:app
instance_class: F2
service_account: $SA
env_variables:
RECEIPT_BUCKET: "$BUCKET"
automatic_scaling:
min_idle_instances: 1
max_instances: 10
target_cpu_utilization: 0.65
max_concurrent_requests: 40
vpc_access_connector:
name: projects/$PROJECT/locations/$REGION/connectors/orders-conn
egress_setting: private-ranges-only
handlers:
- url: /.*
script: auto
secure: always
EOF
# Deploy the new version without sending it any traffic, then send it 10 percent of requests.
gcloud app deploy app.yaml --version=v150 --no-promote --quiet
gcloud app services set-traffic default --splits=v142=0.9,v150=0.1 --split-by=random --quiet
gcloud app versions list --service=default --sort-by=~version.createTime --limit=5
# Only the office may reach the app. The default rule is the last one that is checked.
gcloud app firewall-rules create 100 --action=allow --source-range=203.0.113.0/24 --description="office"
gcloud app firewall-rules update default --action=deny
# A nightly call to /tasks/reconcile.
gcloud scheduler jobs create app-engine orders-nightly --location=$REGION --schedule="30 20 * * *" --time-zone="UTC" \
--service=default --relative-url=/tasks/reconcile --http-method=POST
# Placeholders: pass in your project and the object in Cloud Storage that holds the zipped app.
variable "project_id" {
type = string
}
variable "location_id" {
type = string
default = "asia-south1"
}
variable "source_bucket" {
type = string
}
variable "source_object" {
type = string
default = "orders-api-1.5.0.zip"
}
variable "receipt_bucket" {
type = string
default = "orders-receipts-example"
}
resource "google_service_account" "orders_api" {
account_id = "orders-api"
display_name = "orders-api"
}
resource "google_storage_bucket_iam_member" "receipts" {
bucket = var.receipt_bucket
role = "roles/storage.objectCreator"
member = "serviceAccount:${google_service_account.orders_api.email}"
}
# The App Engine app: one per project, and the location cannot be changed after this.
resource "google_app_engine_application" "app" {
project = var.project_id
location_id = var.location_id
}
resource "google_app_engine_standard_app_version" "v150" {
version_id = "v150"
service = "default"
runtime = "python313"
entrypoint {
shell = "gunicorn -b :$PORT -w 2 main:app"
}
deployment {
zip {
source_url = "https://storage.googleapis.com/${var.source_bucket}/${var.source_object}"
}
}
instance_class = "F2"
service_account = google_service_account.orders_api.email
env_variables = {
RECEIPT_BUCKET = var.receipt_bucket
}
automatic_scaling {
max_concurrent_requests = 40
min_idle_instances = 1
standard_scheduler_settings {
target_cpu_utilization = 0.65
max_instances = 10
}
}
handlers {
url_regex = "/.*"
security_level = "SECURE_ALWAYS"
script {
script_path = "auto"
}
}
# keep the version after a destroy of this resource, and don't stop the service with it
noop_on_destroy = true
delete_service_on_destroy = false
depends_on = [google_app_engine_application.app]
}
# 90 percent of requests stay on the old version, 10 percent go to the new one.
resource "google_app_engine_service_split_traffic" "default" {
service = "default"
migrate_traffic = false
split {
shard_by = "RANDOM"
allocations = {
"v142" = 0.9
"v150" = 0.1
}
}
depends_on = [google_app_engine_standard_app_version.v150]
}
resource "google_app_engine_firewall_rule" "office" {
project = var.project_id
priority = 100
action = "ALLOW"
source_range = "203.0.113.0/24"
description = "office"
depends_on = [google_app_engine_application.app]
}
# Deletes old versions of a service that receive no traffic, keeping the newest few for a quick rollback.
# pip install google-cloud-appengine-admin (uses Application Default Credentials)
import sys
from google.cloud import appengine_admin_v1
def old_versions(project, service="default", keep=3):
services = appengine_admin_v1.ServicesClient()
versions = appengine_admin_v1.VersionsClient()
split = services.get_service(name="apps/%s/services/%s" % (project, service)).split
serving = {v for v, share in split.allocations.items() if share > 0}
parent = "apps/%s/services/%s" % (project, service)
every = sorted(versions.list_versions(parent=parent), key=lambda v: v.create_time, reverse=True)
newest = {v.id for v in every[:keep]}
return [v for v in every if v.id not in serving and v.id not in newest]
if __name__ == "__main__":
project = sys.argv[1]
dry_run = "--delete" not in sys.argv
versions = appengine_admin_v1.VersionsClient()
for v in old_versions(project):
print(("would delete" if dry_run else "deleting"), v.name)
if not dry_run:
versions.delete_version(name=v.name).result()
// dotnet add package Google.Cloud.AppEngine.V1
// Lists the services of an App Engine app, their traffic split and the versions of each, newest first.
// Uses Application Default Credentials (gcloud auth application-default login, or the service account on the machine).
using Google.Cloud.AppEngine.V1;
string project = args.Length > 0 ? args[0] : throw new ArgumentException("Usage: versions <project>");
ServicesClient services = await ServicesClient.CreateAsync();
VersionsClient versions = await VersionsClient.CreateAsync();
await foreach (Service service in services.ListServicesAsync(new ListServicesRequest { Parent = $"apps/{project}" }))
{
string id = service.Id;
var split = string.Join(", ", service.Split.Allocations.Select(a => $"{a.Key}={a.Value:P0}"));
Console.WriteLine($"{id} traffic: {(split.Length == 0 ? "none" : split)}");
var list = new List<Google.Cloud.AppEngine.V1.Version>();
await foreach (var v in versions.ListVersionsAsync(new ListVersionsRequest { Parent = $"apps/{project}/services/{id}" }))
list.Add(v);
foreach (var v in list.OrderByDescending(v => v.CreateTime.ToDateTime()))
{
bool serving = service.Split.Allocations.TryGetValue(v.Id, out var share) && share > 0;
Console.WriteLine($" {v.Id,-10} {v.ServingStatus,-8} runtime={v.Runtime,-10} {(serving ? "gets traffic" : "idle")}");
}
}
Best videos to explore
Videos picked for this service. Each one is labelled with its source, opens on YouTube if you prefer, and loads only when you press play.
Interview questions
BasicWhat is Google App Engine?
It’s Google Cloud’s fully managed platform for web applications. You describe your app in an app.yaml file and deploy with one command, and App Engine runs it on instances it creates, patches and scales. It comes in a standard environment (sandboxed runtimes) and a flexible environment (Docker containers).
BasicWhat is the difference between the standard and flexible environments?
Standard runs your code on supported runtimes in a sandbox, starts instances in seconds, can scale to zero and has a free daily allowance, but doesn’t accept custom Docker images. Flexible runs your Docker container on Compute Engine VMs, supports any language and library, but starts and deploys in minutes, always keeps at least one instance and bills for vCPU, memory and disk.
BasicCan I change the region of an App Engine app?
No. A project can have only one App Engine app, and its region is fixed when you create it. If you chose the wrong one, you need a new project. Decide on the region with data location rules and latency in mind before running gcloud app create.
IntermediateHow do services and versions work together?
An app is made of services, such as a web front end and an API, and each deployment of a service creates a version. Several versions can run at once, and you split traffic between them by IP address, cookie or randomly. That’s how you run a canary release or roll back.
IntermediateHow do you release a new version of an App Engine service safely?
Deploy with --no-promote so the new version gets no traffic, test it on its own URL, then use set-traffic to send a small share of requests, watch errors and latency, and move the rest in steps. Keep the old version for a quick rollback, and delete it once you’re confident.
IntermediateWhy are requests slow after a quiet period on the standard environment?
The app scaled to zero, so a request has to wait for a new instance to start. Set min_idle_instances for user-facing services, keep start-up work light and use warmup requests. The trade-off is that idle instances cost money.
AdvancedHow would you choose between App Engine and Cloud Run for a new web service?
Cloud Run takes any container, scales to zero, has long request timeouts and flexible billing, so it suits many new services. App Engine standard suits teams that like the app.yaml model, the built-in services and versions and traffic splitting, and apps already written for it. For existing App Engine apps, moving is optional and should be planned, not forced.
AdvancedHow do you give an App Engine app access to private resources safely?
Use a Serverless VPC Access connector (or Direct VPC egress where available), name it in app.yaml, send only private ranges through it with the egress setting, and allow the connector’s range in the firewall of the database. Run the app as its own service account with minimal roles, and pool database connections so a scale-out doesn’t exhaust them.
AdvancedHow would you replace the old task queue and cron features in a legacy App Engine app?
Use Cloud Tasks for background work, with an HTTP target in your app that handles each task and returns success or failure for retries, and Cloud Scheduler for cron jobs, calling an App Engine handler with the right service and URL. Secure the handlers so that only those callers can reach them, for example with IAP or a header check.
AdvancedWhat would you do about an App Engine app that runs on an old runtime?
Check the runtime’s support dates, test the newer runtime on a new version that receives no traffic, replace removed bundled APIs with Cloud Tasks, Cloud Scheduler, Firestore and Memorystore, and then migrate traffic in steps. Use the version limit and traffic splitting to keep a fast path back.
Similar or alternative services on other clouds
| Capability | AWS | Azure | Google Cloud |
|---|---|---|---|
| Service | AWS Elastic Beanstalk | Azure App Service | Google App Engine |
| Deploy unit | Zip, WAR or Docker setup | Zip, container or source from Git | Source code plus app.yaml, or a Docker image on flexible |
| Scale to zero | No | No | Yes on the standard environment |
| What you pay for | The resources it creates, nothing for the service | The plan, per instance-hour | Instance hours, with a free daily allowance on standard |
| Release strategy | Deployment policies and CNAME swap | Deployment slots and swap | Versions with traffic splitting |
| Microservices | Several environments per application | Several apps on a plan | Services inside one app |
| Region choice | Chosen per environment | Chosen per plan | One region per project, permanent |
| Direction | Active, old platform branches retire | Active | Active, many new services start on Cloud Run |
If you want containers that scale to zero without the App Engine model, look at Cloud Run. For small event-driven functions use Cloud Run functions, and for Kubernetes use Google Kubernetes Engine. App Engine apps usually keep relational data in Cloud SQL and files in Cloud Storage.
Did you find this article helpful?
Your answer helps us improve this page for the next reader.
Sources and further reading
CloudBrum wrote this page in its own words, using the provider’s public documentation listed below as the reference. Features, limits, names and prices change, so confirm anything that matters on the provider’s own pages before you decide.
- App Engine documentation overviewGoogle Cloud
- App Engine standard environment overviewGoogle Cloud
- Choosing an App Engine environmentGoogle Cloud
- app.yaml reference for the standard environmentGoogle Cloud
- Splitting trafficGoogle Cloud
- Controlling App Engine access with firewall rulesGoogle Cloud
- Connecting to a VPC network from App EngineGoogle Cloud
- App Engine pricingGoogle Cloud
- Terraform Google provider: google_app_engine_standard_app_versionHashiCorp
