Cloudflare Workers
Aero2 runs on Cloudflare Workers, a serverless compute platform that executes JavaScript/TypeScript at the edge.
Runtime
- V8 isolates: Each request runs in a lightweight V8 isolate (not a container). This provides fast cold starts and strong isolation between requests.
- Globally distributed: Code runs in Cloudflare's 300+ data centers worldwide, close to users.
- No cold starts: Workers use V8 isolates instead of containers, so startup time is measured in milliseconds.
Limits
| Resource | Free Plan | Paid Plan (Bundled) |
|---|---|---|
| CPU time per request | 10 ms | 30 seconds |
| Memory | 128 MB | 128 MB |
| Worker size (compressed) | 1 MB | 10 MB |
| Environment variables | 64 | 128 |
| Subrequests per request | 50 | 1000 |
Aero2 uses the paid plan to accommodate JWT signing operations and D1 queries that may exceed the free tier CPU limit.
Compatibility
The Worker is configured with:
{
"compatibility_date": "2026-01-20",
"compatibility_flags": ["nodejs_compat"]
}compatibility_date: Locks the Worker to a specific set of runtime behaviors. Update this periodically to pick up new features.nodejs_compat: Enables Node.js-compatible APIs (crypto, buffer, etc.) needed for JWT operations and password hashing.
Wrangler CLI
Wrangler is the CLI tool for developing, testing, and deploying Workers.
Key Commands
# Start local development server
npx wrangler dev
# Deploy to Cloudflare
npx wrangler deploy
# Deploy to a specific environment
npx wrangler deploy --env production
npx wrangler deploy --env qa
# Stream live logs
npx wrangler tail --env production
# Manage secrets
npx wrangler secret put SECRET_NAME --env production
npx wrangler secret list --env production
# Generate TypeScript types from bindings
npx wrangler types
# Rollback a deployment
npx wrangler rollback --env productionWorker Configuration
The Worker configuration lives in wrangler.json at the project root. Key sections:
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "aero2",
"main": "src/backend/index.ts",
"compatibility_date": "2026-01-20",
"compatibility_flags": ["nodejs_compat"],
// D1 database binding
"d1_databases": [
{ "binding": "DB", "database_name": "aero2", "database_id": "..." }
],
// Durable Object for JWKS key management
"durable_objects": {
"bindings": [
{ "name": "JWKS", "class_name": "JWKSDurableObject" }
]
},
// Observability
"observability": {
"enabled": true,
"head_sampling_rate": 1
},
// Environment-specific overrides
"env": {
"production": {
"routes": [
{ "pattern": "aero2.dev/*", "zone_name": "aero2.dev" },
{ "pattern": "*.aero2.dev/*", "zone_name": "aero2.dev" }
],
"vars": {
"PLATFORM_DOMAIN": "aero2.dev",
"AUDIENCE": "aero2",
"CF_ZONE_ID": "set-production-zone-id"
}
}
}
}Bindings
Aero2 uses the following Cloudflare bindings:
| Binding | Type | Purpose |
|---|---|---|
DB | D1 Database | All persistent data (users, sessions, tokens, etc.) |
JWKS | Durable Object | JWKS key generation, rotation, and signing |
Future bindings planned:
| Binding | Type | Purpose |
|---|---|---|
RATE_LIMITER | Durable Object | Persistent rate limiting across isolates |
ASSETS | R2 Bucket | Branding assets (logos, favicons) |
WEBHOOK_QUEUE | Queue | Async webhook delivery |
Environment Variables
Set in wrangler.json under vars or via wrangler secret put:
| Variable | Type | Description |
|---|---|---|
PLATFORM_DOMAIN | var | Base domain (e.g., aero2.dev) |
AUDIENCE | var | Default token audience for dashboard context |
CF_ZONE_ID | var | Cloudflare zone id for custom hostname operations |
MASTER_KEY | secret | Encryption key for secrets at rest |
BOOTSTRAP_ADMIN_EMAIL | secret | First admin user email |
CF_API_TOKEN | secret | Cloudflare API token for custom hostnames |
GITHUB_CLIENT_ID | secret | GitHub OAuth app client ID |
GITHUB_CLIENT_SECRET | secret | GitHub OAuth app client secret |
GOOGLE_CLIENT_ID | secret | Google OAuth client ID |
GOOGLE_CLIENT_SECRET | secret | Google OAuth client secret |