The app.yaml configuration file reference — all settings, common patterns, and best practices for configuring your App Engine services.


What is app.yaml?

app.yaml is the primary configuration file for every App Engine service. It defines how your application runs: the runtime, scaling behavior, environment variables, URL routing, and more. Every service must have one.

At minimum, it needs a runtime:

runtime: python312

Everything else is optional, but most services need more configuration than this.


Standard Environment Settings

Required fields

runtime: python312     # Required. The language runtime version.

Service and instance

# Service name (omit for 'default' service)
service: my-service
 
# Instance class (hardware allocation)
instance_class: F2     # F1 (default), F2, F4, F4_1G for automatic scaling
                       # B1, B2, B4, B8 for basic/manual scaling

Scaling configuration

Choose one of three scaling types:

Automatic scaling (default):

automatic_scaling:
  min_instances: 0              # Scale to zero when idle
  max_instances: 10             # Maximum instances
  target_cpu_utilization: 0.6   # Scale up at 60% CPU
  target_throughput_utilization: 0.6
  max_concurrent_requests: 100
  min_pending_latency: 30ms
  max_pending_latency: automatic
  min_idle_instances: 0
  max_idle_instances: automatic

Basic scaling:

instance_class: B2
 
basic_scaling:
  max_instances: 5
  idle_timeout: 10m

Manual scaling:

instance_class: B2
 
manual_scaling:
  instances: 3

Environment variables

env_variables:
  NODE_ENV: "production"
  DATABASE_URL: "postgres://user:pass@host:5432/db"
  API_KEY: "your-api-key"

Warning: Do not put secrets in env_variables. Anyone with access to your source code or the App Engine console can read them. Use Secret Manager for sensitive values.

URL handlers

Handlers define how App Engine routes incoming requests:

handlers:
  # Serve static files from /static directory
  - url: /static
    static_dir: static
    expiration: "30d"
    http_headers:
      Cache-Control: "public, max-age=2592000"
 
  # Serve a specific static file
  - url: /favicon\.ico
    static_files: favicon.ico
    upload: favicon\.ico
 
  # Pattern-match static files
  - url: /(.*\.(gif|png|jpg|css|js))$
    static_files: static/\1
    upload: static/.*\.(gif|png|jpg|css|js)$
 
  # Route everything else to your application
  - url: /.*
    script: auto
    secure: always       # Force HTTPS
    login: admin         # Require admin authentication

Handler settings

SettingValuesDescription
urlRegex patternURL pattern to match
static_dirDirectory pathServe all files in this directory
static_filesFile pathServe a specific file
uploadRegex patternWhich files to upload with deployment
script: autoautoRoute to your application code
securealways, optional, neverHTTPS enforcement
loginadmin, required, optionalAuthentication requirement
expirationDuration stringCache expiration for static files
http_headersKey-value mapCustom HTTP headers for responses

Error handlers

error_handlers:
  - error_code: over_quota
    file: over_quota.html
  - error_code: dos_api_denial
    file: dos_deny.html
  - error_code: timeout
    file: timeout.html

Inbound services

inbound_services:
  - warmup               # Enable warmup requests for pre-loading

Flexible Environment Settings

The Flexible environment uses env: flex and has additional configuration options:

runtime: python
env: flex                    # Required for flexible
 
# OR use custom runtime
# runtime: custom
# env: flex
 
# Resource allocation
resources:
  cpu: 2
  memory_gb: 4
  disk_size_gb: 20
 
# VPC networking
network:
  name: my-vpc
  subnetwork_name: my-subnet
  instance_ip_mode: INTERNAL
 
# Custom entrypoint
entrypoint: gunicorn -b :$PORT main:app
 
# Automatic scaling (flex)
automatic_scaling:
  min_num_instances: 1
  max_num_instances: 10
  cpu_utilization:
    target_utilization: 0.65
  cool_down_period_sec: 120
 
# Manual scaling (flex)
# manual_scaling:
#   instances: 3
 
# Health checks
liveness_check:
  path: "/liveness"
  check_interval_sec: 30
  timeout_sec: 4
  failure_threshold: 4
  success_threshold: 2
 
readiness_check:
  path: "/readiness"
  check_interval_sec: 5
  timeout_sec: 4
  failure_threshold: 2
  success_threshold: 2
  app_start_timeout_sec: 300

Flexible-only settings

SettingDescription
env: flexMarks this as a Flexible environment config
resources.cpuNumber of vCPUs (1, 2, 4, 8, etc.)
resources.memory_gbMemory in GB
resources.disk_size_gbPersistent disk size
networkVPC network configuration
entrypointCustom start command
liveness_checkHealth check for instance restart
readiness_checkHealth check for traffic routing
beta_settingsAdvanced features (e.g., Cloud SQL connection)

Cloud SQL connection (Flexible)

beta_settings:
  cloud_sql_instances: my-project:us-central1:my-instance

Common Configurations

Minimal Python app

runtime: python312

That’s it. App Engine uses sensible defaults for everything else.

Static website

runtime: python312
handlers:
  - url: /
    static_files: index.html
    upload: index.html
  - url: /(.*)
    static_files: \1
    upload: (.*)

Node.js API with environment variables

runtime: nodejs20
instance_class: F2
 
env_variables:
  NODE_ENV: "production"
 
automatic_scaling:
  min_instances: 0
  max_instances: 5

Python app with Cloud SQL

runtime: python312
instance_class: F4
 
env_variables:
  DB_HOST: "/cloudsql/my-project:us-central1:my-instance"
 
automatic_scaling:
  min_instances: 1
  max_instances: 10

Java app with manual scaling

runtime: java21
instance_class: B4
 
manual_scaling:
  instances: 2

Flexible custom runtime

runtime: custom
env: flex
 
resources:
  cpu: 2
  memory_gb: 4
 
automatic_scaling:
  min_num_instances: 1
  max_num_instances: 5

Best Practices

PracticeWhy
Use secure: alwaysForce HTTPS on all requests
Use Secret Manager for secretsenv_variables are visible in the console
Add app.yaml to .gitignore if it contains secretsPrevents accidental credential exposure
Set appropriate instance_classMatch instance size to your memory/CPU needs
Use min_instances: 0 for cost savingsScales to zero when there’s no traffic
Use min_instances: 1 to avoid cold startsKeeps one instance warm for low-latency responses
Enable warmup requestsPre-load your app before real traffic arrives
Set max_instances to cap costsPrevents runaway scaling from unexpected traffic spikes
Use different services for different environmentsSeparate staging and production via service names

Tip: Use separate GCP projects for staging and production (rather than different services) for better isolation. Services within the same project share quotas and billing.


TL;DR

  • app.yaml is the required configuration file for every App Engine service.
  • Minimum config: just runtime: python312. Everything else has defaults.
  • Key sections: runtime, service, instance_class, scaling, env_variables, handlers.
  • Standard uses F-class (auto scaling) or B-class (basic/manual) instances.
  • Flexible adds env: flex, resources, network, and health checks.
  • Never put secrets in env_variables — use Secret Manager.
  • Always set secure: always to enforce HTTPS.

Resources

app.yaml Reference (Standard) Complete configuration reference for the Standard environment.

app.yaml Reference (Flexible) Complete configuration reference for the Flexible environment.

Secret Manager Documentation Secure storage for API keys, passwords, and certificates.

Scaling Options Detailed guide to automatic, basic, and manual scaling configuration.

Standard vs Flexible Environment differences that affect app.yaml settings.