google-app-engine

Status: Production Ready Last Updated: 2026-01-24 Dependencies: Google Cloud SDK (gcloud CLI) Skill Version: 1.0.0

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "google-app-engine" with this command: npx skills add jezweb/claude-skills/jezweb-claude-skills-google-app-engine

Google App Engine

Status: Production Ready Last Updated: 2026-01-24 Dependencies: Google Cloud SDK (gcloud CLI) Skill Version: 1.0.0

Quick Start (10 Minutes)

  1. Prerequisites

Install Google Cloud SDK

macOS

brew install google-cloud-sdk

Or download from https://cloud.google.com/sdk/docs/install

Authenticate

gcloud auth login gcloud config set project YOUR_PROJECT_ID

Enable required APIs

gcloud services enable appengine.googleapis.com gcloud services enable sqladmin.googleapis.com gcloud services enable secretmanager.googleapis.com

  1. Create app.yaml

app.yaml - Standard Environment (Python 3.12)

runtime: python312 instance_class: F2

env_variables: DJANGO_SETTINGS_MODULE: "myproject.settings.production"

handlers:

Static files (served directly by App Engine)

  • url: /static static_dir: staticfiles/ secure: always

All other requests go to the app

  • url: /.* script: auto secure: always

automatic_scaling: min_instances: 0 max_instances: 10 target_cpu_utilization: 0.65

  1. Deploy

Deploy to App Engine

gcloud app deploy

Deploy with specific version

gcloud app deploy --version=v1 --no-promote

View logs

gcloud app logs tail -s default

Standard vs Flexible Environment

Standard Environment (Recommended for Most Apps)

Use when: Building typical web apps, APIs, or services that fit within runtime constraints.

Aspect Standard

Startup Fast (milliseconds)

Scaling Scale to zero

Pricing Pay per request

Runtimes Python 3.8-3.12

Instance Classes F1, F2, F4, F4_1G

Max Request 60 seconds

Background Cloud Tasks only

app.yaml - Standard

runtime: python312 instance_class: F2

Flexible Environment

Use when: Need custom runtimes, Docker, longer request timeouts, or background threads.

Aspect Flexible

Startup Slower (minutes)

Scaling Min 1 instance

Pricing Per-hour VM

Runtimes Any (Docker)

Max Request 60 minutes

Background Native threads

app.yaml - Flexible

runtime: python env: flex

runtime_config: runtime_version: "3.12"

resources: cpu: 1 memory_gb: 0.5 disk_size_gb: 10

automatic_scaling: min_num_instances: 1 max_num_instances: 5

Cost Warning: Flexible always runs at least 1 instance (~$30-40/month minimum).

Cloud SQL Connection

Standard Environment (Unix Socket)

App Engine Standard connects to Cloud SQL via Unix sockets, not TCP/IP.

settings.py

import os

if os.getenv('GAE_APPLICATION'): # Production: Cloud SQL via Unix socket DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ['DB_NAME'], 'USER': os.environ['DB_USER'], 'PASSWORD': os.environ['DB_PASSWORD'], 'HOST': f"/cloudsql/{os.environ['CLOUD_SQL_CONNECTION_NAME']}", 'PORT': '', # Empty for Unix socket } } else: # Local development: Cloud SQL Proxy or local DB DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.environ.get('DB_NAME', 'localdb'), 'USER': os.environ.get('DB_USER', 'postgres'), 'PASSWORD': os.environ.get('DB_PASSWORD', ''), 'HOST': '127.0.0.1', 'PORT': '5432', } }

app.yaml

env_variables: DB_NAME: "mydb" DB_USER: "myuser" CLOUD_SQL_CONNECTION_NAME: "project:region:instance"

CRITICAL: Beta settings for Cloud SQL socket

beta_settings: cloud_sql_instances: "project:region:instance"

CRITICAL: The beta_settings.cloud_sql_instances enables the Unix socket. Without it, connection fails.

Local Development with Cloud SQL Proxy

Download and run Cloud SQL Proxy

cloud-sql-proxy PROJECT:REGION:INSTANCE --port=5432

Or use Docker

docker run -p 5432:5432
gcr.io/cloud-sql-connectors/cloud-sql-proxy:2.8.0
PROJECT:REGION:INSTANCE

Static Files with Cloud Storage

Option 1: App Engine Static Handlers (Simple)

app.yaml

handlers:

  • url: /static static_dir: staticfiles/ secure: always expiration: "1d"

Collect static files before deploy

python manage.py collectstatic --noinput gcloud app deploy

Limitation: Files bundled with deploy, limited to 32MB per file.

Option 2: Cloud Storage (Recommended for Production)

settings.py

from google.cloud import storage

GS_BUCKET_NAME = os.environ.get('GS_BUCKET_NAME') STATICFILES_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage' DEFAULT_FILE_STORAGE = 'storages.backends.gcloud.GoogleCloudStorage'

Or with django-storages

STORAGES = { "default": { "BACKEND": "storages.backends.gcloud.GoogleCloudStorage", "OPTIONS": { "bucket_name": GS_BUCKET_NAME, "location": "media", }, }, "staticfiles": { "BACKEND": "storages.backends.gcloud.GoogleCloudStorage", "OPTIONS": { "bucket_name": GS_BUCKET_NAME, "location": "static", }, }, }

Install django-storages

pip install django-storages[google]

Create bucket with public access for static files

gsutil mb -l us-central1 gs://YOUR_BUCKET_NAME gsutil iam ch allUsers:objectViewer gs://YOUR_BUCKET_NAME

Environment Variables and Secrets

Simple: app.yaml env_variables

app.yaml - NOT for secrets!

env_variables: DJANGO_SETTINGS_MODULE: "myproject.settings.production" DEBUG: "False"

Warning: app.yaml is committed to source control. Never put secrets here.

Production: Secret Manager

settings.py

from google.cloud import secretmanager

def get_secret(secret_id, version="latest"): """Fetch secret from Google Secret Manager.""" client = secretmanager.SecretManagerServiceClient() project_id = os.environ.get('GOOGLE_CLOUD_PROJECT') name = f"projects/{project_id}/secrets/{secret_id}/versions/{version}" response = client.access_secret_version(request={"name": name}) return response.payload.data.decode("UTF-8")

Usage

if os.getenv('GAE_APPLICATION'): SECRET_KEY = get_secret('django-secret-key') DB_PASSWORD = get_secret('db-password')

Create secrets

echo -n "your-secret-key" | gcloud secrets create django-secret-key --data-file=- echo -n "db-password" | gcloud secrets create db-password --data-file=-

Grant App Engine access

gcloud secrets add-iam-policy-binding django-secret-key
--member="serviceAccount:YOUR_PROJECT@appspot.gserviceaccount.com"
--role="roles/secretmanager.secretAccessor"

Scaling Configuration

Automatic Scaling (Default)

automatic_scaling: min_instances: 0 # Scale to zero when idle max_instances: 10 # Cap maximum instances target_cpu_utilization: 0.65 target_throughput_utilization: 0.6 max_concurrent_requests: 80 min_pending_latency: 30ms max_pending_latency: automatic

Basic Scaling (Background Tasks)

basic_scaling: max_instances: 5 idle_timeout: 5m

Use for: Services that need to run background work without scaling to zero immediately.

Manual Scaling (Fixed Instances)

manual_scaling: instances: 3

Use for: Predictable workloads, WebSocket connections, or when you need guaranteed capacity.

Instance Classes

Class Memory CPU Cost/hour

F1 256 MB 600 MHz $0.05

F2 512 MB 1.2 GHz $0.10

F4 1 GB 2.4 GHz $0.20

F4_1G 2 GB 2.4 GHz $0.30

Recommended for Django

instance_class: F2 # 512MB usually sufficient

Upgrade to F4 if you see memory errors or slow response times.

Known Issues Prevention

This skill prevents 6 documented issues:

Issue #1: Cloud SQL Connection Refused

Error: could not connect to server: Connection refused

Why It Happens: Missing beta_settings.cloud_sql_instances in app.yaml Prevention: Always include:

beta_settings: cloud_sql_instances: "project:region:instance"

Issue #2: Static Files 404

Error: Static files return 404 after deploy Why It Happens: collectstatic not run, or handler order wrong Prevention:

python manage.py collectstatic --noinput

And ensure static handler comes before catch-all:

handlers:

  • url: /static static_dir: staticfiles/
  • url: /.* script: auto

Issue #3: 502 Bad Gateway

Error: 502 errors on first request or under load Why It Happens: Cold start timeout, app takes too long to initialize Prevention:

  • Optimize app startup (lazy imports, connection pooling)

  • Use min_instances: 1 to avoid cold starts

  • Increase instance_class for more CPU/memory

Issue #4: Memory Limit Exceeded

Error: Exceeded soft memory limit in logs Why It Happens: F1 class (256MB) too small for Django + dependencies Prevention: Use instance_class: F2 minimum for Django apps

Issue #5: Request Timeout

Error: DeadlineExceededError after 60 seconds Why It Happens: Standard environment has 60s request limit Prevention:

  • Move long tasks to Cloud Tasks

  • Use Flexible environment for longer timeouts

  • Optimize database queries

Issue #6: Secret Key in Source Control

Error: Django SECRET_KEY exposed in git history Why It Happens: Putting secrets in app.yaml env_variables Prevention: Use Secret Manager (see Environment Variables section)

Deployment Commands

Deploy default service

gcloud app deploy

Deploy specific service

gcloud app deploy app.yaml --service=api

Deploy without promoting (for testing)

gcloud app deploy --version=v2 --no-promote

Split traffic between versions

gcloud app services set-traffic default --splits=v1=0.5,v2=0.5

Promote version

gcloud app versions migrate v2

View logs

gcloud app logs tail -s default

Open app in browser

gcloud app browse

List versions

gcloud app versions list

Delete old versions

gcloud app versions delete v1 v2 --quiet

Multi-Service Architecture

myproject/ ├── app.yaml # Default service ├── api/ │ └── app.yaml # API service ├── worker/ │ └── app.yaml # Background worker └── dispatch.yaml # URL routing

dispatch.yaml

dispatch:

  • url: "/api/" service: api
  • url: "/tasks/" service: worker

Deploy all services

gcloud app deploy app.yaml api/app.yaml worker/app.yaml dispatch.yaml

Common Patterns

Health Check Endpoint

urls.py

urlpatterns = [ path('_ah/health', lambda r: HttpResponse('ok')), # ... other urls ]

app.yaml

liveness_check: path: "/_ah/health" check_interval_sec: 30 timeout_sec: 4 failure_threshold: 2 success_threshold: 2

readiness_check: path: "/_ah/health" check_interval_sec: 5 timeout_sec: 4 failure_threshold: 2 success_threshold: 2

Warmup Requests

app.yaml

inbound_services:

  • warmup

urls.py

urlpatterns = [ path('_ah/warmup', warmup_view), ]

views.py

def warmup_view(request): """Pre-warm caches and connections.""" from django.db import connection connection.ensure_connection() return HttpResponse('ok')

HTTPS Redirect

app.yaml

handlers:

  • url: /.* script: auto secure: always # Redirects HTTP to HTTPS

Local Development

Using Cloud SQL Proxy

Terminal 1: Run Cloud SQL Proxy

cloud-sql-proxy PROJECT:REGION:INSTANCE --port=5432

Terminal 2: Run Django

export DB_HOST=127.0.0.1 export DB_PORT=5432 python manage.py runserver

Using dev_appserver (Legacy)

Not recommended - use Django's runserver instead

dev_appserver.py app.yaml

Environment Detection

settings.py

import os

Detect App Engine environment

IS_GAE = os.getenv('GAE_APPLICATION') is not None IS_GAE_LOCAL = os.getenv('GAE_ENV') == 'localdev'

if IS_GAE: DEBUG = False ALLOWED_HOSTS = ['.appspot.com', '.your-domain.com'] else: DEBUG = True ALLOWED_HOSTS = ['localhost', '127.0.0.1']

Bundled Resources

Templates (templates/)

  • app.yaml

  • Standard environment configuration

  • app-flex.yaml

  • Flexible environment configuration

  • requirements.txt

  • Common dependencies for App Engine

References (references/)

  • instance-classes.md

  • Detailed instance class comparison

  • common-errors.md

  • Error messages and solutions

Official Documentation

Dependencies

requirements.txt

gunicorn>=21.0.0 google-cloud-secret-manager>=2.16.0 google-cloud-storage>=2.10.0 django-storages[google]>=1.14.0 psycopg2-binary>=2.9.9 # For PostgreSQL

Production Checklist

  • SECRET_KEY in Secret Manager (not app.yaml)

  • DEBUG = False in production settings

  • ALLOWED_HOSTS configured for your domain

  • collectstatic runs before deploy

  • beta_settings.cloud_sql_instances set

  • Instance class appropriate (F2+ for Django)

  • HTTPS enforced (secure: always )

  • Health check endpoint configured

  • Error monitoring set up (Cloud Error Reporting)

Last verified: 2026-01-24 | Skill version: 1.0.0

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

agent-development

No summary provided by upstream source.

Repository SourceNeeds Review
361-jezweb
Coding

developer-toolbox

No summary provided by upstream source.

Repository SourceNeeds Review
359-jezweb
Coding

typescript-mcp

No summary provided by upstream source.

Repository SourceNeeds Review
339-jezweb
Coding

cloudflare-python-workers

No summary provided by upstream source.

Repository SourceNeeds Review
321-jezweb