1---2name: deno-deploy3description: Use when deploying Deno apps to production, asking about Deno Deploy, or working with `deno deploy` CLI commands. Covers deployment workflows, environment variables, KV database access, custom domains, the --tunnel flag for local development, and the `deno deploy` command reference.4license: MIT5metadata:6 author: denoland7 version: "1.5"8---910# Deno Deploy1112This skill provides guidance for deploying applications to Deno Deploy.1314## Scope Boundaries1516This skill applies **only** to Deno Deploy questions. Follow these rules:1718- If the user asks about **AWS Lambda, Vercel, Netlify, Google Cloud Run, Docker, Kubernetes, or any other deployment platform**, answer using that platform directly. Do not mention Deno Deploy at all — not as an alternative, not as a comparison, not as a suggestion.19- If the user asks about **running a local Deno script** (not deploying), answer the local question directly. Do not mention Deno Deploy, deployment, or the `--tunnel` flag.20- Do not include `deno deploy` commands, Deno KV, or Deno Deploy environment variable configuration in responses about other platforms or local-only scripts.21- Only discuss Deno Deploy when the user explicitly asks about Deno Deploy or deploying a Deno application to production.2223## Important: Use `deno deploy`, NOT `deployctl`2425**Always use the `deno deploy` command.** Do NOT use `deployctl`.2627- `deployctl` is for Deno Deploy Classic (deprecated)28- `deno deploy` is the modern, integrated command built into the Deno CLI29- **Requires Deno >= 2.4.2** - the `deno deploy` subcommand was introduced in Deno 2.43031## When Unsure About CLI Flags3233**Always run `--help` before guessing at flags.** The `deno deploy` subcommand has many flags, and they change between versions. When you're unsure what a command accepts:3435```bash36# See all subcommands37deno deploy --help3839# See flags for a specific subcommand40deno deploy create --help41deno deploy env --help42deno deploy database --help43```4445This takes seconds and prevents repeated trial-and-error failures. Never assume a flag exists — check first.4647## Deployment Workflow4849**Always show the core deploy command first** — then explain diagnostic steps. When a user asks "how do I deploy?", lead with the actual command (`deno deploy --prod`) before covering pre-flight checks and configuration.5051### Step 1: Locate the App Directory5253Before running any deploy commands, find where the Deno app is located:5455```bash56# Check if deno.json exists in current directory57if [ -f "deno.json" ] || [ -f "deno.jsonc" ]; then58 echo "APP_DIR: $(pwd)"59else60 # Look for deno.json in immediate subdirectories61 find . -maxdepth 2 -name "deno.json" -o -name "deno.jsonc" 2>/dev/null | head -562fi63```6465All deploy commands must run from the app directory.6667### Step 2: Pre-Flight Checks6869Check Deno version and existing configuration:7071```bash72# Check Deno version (must be >= 2.4.2)73deno --version | head -17475# Check for existing deploy config76grep -E '"org"|"app"' deno.json deno.jsonc 2>/dev/null || echo "NO_DEPLOY_CONFIG"77```7879### Step 3: Check for Startup Dependencies8081Before deploying, check if the app connects to a database or external service at startup (e.g., top-level `await initDb()` in `main.ts`). If it does, the deploy will fail during warmup because the database doesn't exist yet.8283**If the app has startup database dependencies, follow this order:**84851. **Create the app with `--no-wait`** so a warmup failure doesn't block you:86 ```bash87 deno deploy create \88 --org <ORG_NAME> --app <APP_NAME> \89 --source local --runtime-mode dynamic --entrypoint main.ts \90 --build-timeout 5 --build-memory-limit 1024 --region us \91 --no-wait92 ```93942. **Provision and assign the database:**95 ```bash96 deno deploy database provision my-db --kind prisma --region us-east-197 deno deploy database assign my-db --app <APP_NAME>98 ```991003. **Redeploy** (now the database exists, warmup will succeed):101 ```bash102 deno deploy --prod103 ```104105If the app has no startup dependencies, skip this step and deploy normally below.106107### Step 4: Deploy Based on Configuration108109**If `deploy.org` AND `deploy.app` exist in deno.json:**110```bash111# Build if needed (Fresh, Astro, etc.)112deno task build113114# Deploy to production115deno deploy --prod116```117118**If NO deploy config exists:**119120**Apps must be created before they can be deployed to.** You cannot run `deno deploy --prod` until an app exists.121122**IMPORTANT: Ask the user first** - Do they have an existing app on Deno Deploy, or do they need to create a new one?123124**If they have an existing app**, add the config directly to deno.json:125```json126{127 "deploy": {128 "org": "<ORG_NAME>",129 "app": "<APP_NAME>"130 }131}132```133The org name is in the Deno Deploy console URL (e.g., `console.deno.com/your-org-name`). Once this config is in place, subsequent deploys just need `deno deploy --prod`.134135**If they need to create a new app:**136137The CLI needs an organization name. Find it at https://console.deno.com - the org is in the URL path (e.g., `console.deno.com/your-org-name`).138139**Interactive creation** (opens a browser — only works when a human is at the keyboard):140```bash141deno deploy create --org <ORG_NAME>142# A browser window opens - complete the app creation there143```144145**Non-interactive creation** (use when an AI agent is performing the deploy, or in CI/CD):146```bash147deno deploy create \148 --org <ORG_NAME> \149 --app <APP_NAME> \150 --source local \151 --runtime-mode dynamic \152 --entrypoint main.ts \153 --build-timeout 5 \154 --build-memory-limit 1024 \155 --region us156```157158The create command also does the initial deploy. After it completes, `deno.json` is updated with `deploy.org` and `deploy.app` automatically. From that point on, subsequent deploys only need:159```bash160deno deploy --prod161```162163After completion, verify the config was saved:164```bash165grep -E '"org"|"app"' deno.json166```167168**When an AI agent is performing the deployment**, always use the non-interactive flow with explicit flags. The interactive flow requires browser windows and terminal prompts that agents cannot navigate.169170## Core Commands171172### Production Deployment173174```bash175deno deploy --prod176```177178### Preview Deployment179180```bash181deno deploy182```183184Preview deployments create a unique URL for testing without affecting production.185186### Targeting Specific Apps187188```bash189deno deploy --org my-org --app my-app --prod190```191192### Configuring an Entrypoint193194Set the entrypoint in your `deno.json` (this is used by `deno deploy create` during app creation):195196```json197{198 "deploy": {199 "entrypoint": "main.ts"200 }201}202```203204Note: `--entrypoint` is a flag on `deno deploy create`, not on `deno deploy` itself.205206### Additional Flags207208These flags are available on `deno deploy create` (and apply during the initial deploy):209210| Flag | Purpose |211|------|---------|212| `--allow-node-modules` | Include node_modules directory in upload |213| `--no-wait` | Skip waiting for the build to complete |214215## Creating Apps (Non-Interactive Reference)216217When any flag beyond `--org` is provided, `deno deploy create` runs in non-interactive mode — all required flags must be specified. This is the recommended approach for AI agents and CI/CD pipelines.218219### Required Flags220221| Flag | Description |222|------|-------------|223| `--org <name>` | Organization name |224| `--app <name>` | Application name (becomes your URL: `<app>.deno.dev`) |225| `--source <local\|github>` | Deploy from local files or a GitHub repo |226| `--build-timeout <minutes>` | Build timeout: 5, 10, 15, 20, 25, or 30 |227| `--build-memory-limit <MB>` | Memory limit: 1024, 2048, 3072, or 4096 |228| `--region <region>` | Deployment region: us, eu, or global |229230### GitHub Source Flags231232When using `--source github`, you also need:233234| Flag | Description |235|------|-------------|236| `--owner <name>` | GitHub repository owner |237| `--repo <name>` | GitHub repository name |238239### Build Configuration Flags240241| Flag | Description |242|------|-------------|243| `--app-directory <path>` | Path to app directory (for monorepos) |244| `--framework-preset <preset>` | Framework preset (see [Frameworks](references/FRAMEWORKS.md)) |245| `--install-command <cmd>` | Custom install command |246| `--build-command <cmd>` | Custom build command |247| `--pre-deploy-command <cmd>` | Command to run before deploy |248| `--do-not-use-detected-build-config` | Skip auto-detection of framework config |249250The CLI auto-detects your framework and build configuration. If a framework is detected, you can skip `--install-command`, `--build-command`, `--pre-deploy-command`, and `--runtime-mode` — they'll be inferred from the preset. Use `--do-not-use-detected-build-config` to override detection. **When using this flag, all three build commands (`--install-command`, `--build-command`, `--pre-deploy-command`) plus `--runtime-mode` become required** — omitting any of them causes exit code 2.251252### Runtime Mode Flags253254You must pick a runtime mode with `--runtime-mode <dynamic|static>` (unless a framework preset handles it).255256**Dynamic mode** (for apps with a server):257258| Flag | Description |259|------|-------------|260| `--entrypoint <path>` | Entry file (required for dynamic mode) |261| `--arguments <args>` | Arguments passed to entrypoint (repeatable) |262| `--working-directory <cwd>` | Working directory for the process |263264**Static mode** (for static sites):265266| Flag | Description |267|------|-------------|268| `--static-dir <dir>` | Directory to serve static files from (required) |269| `--single-page-app` | Serve index.html for routes that don't match a file |270271### Other Flags272273| Flag | Description |274|------|-------------|275| `--dry-run` | Validate everything without actually creating the app |276| `--no-wait` | Don't wait for the build to complete |277| `--allow-node-modules` | Include node_modules in the upload |278279### Examples280281**Simple Deno server:**282```bash283deno deploy create \284 --org my-org --app my-api \285 --source local \286 --runtime-mode dynamic --entrypoint main.ts \287 --build-timeout 5 --build-memory-limit 1024 --region us288```289290**Fresh app (framework auto-detected):**291```bash292deno deploy create \293 --org my-org --app my-fresh-app \294 --source local \295 --build-timeout 5 --build-memory-limit 1024 --region us296```297298**Next.js from GitHub:**299```bash300deno deploy create \301 --org my-org --app my-next-app \302 --source github --owner my-github-user --repo my-next-repo \303 --framework-preset Next \304 --build-timeout 15 --build-memory-limit 2048 --region us \305 --allow-node-modules306```307308**Static site:**309```bash310deno deploy create \311 --org my-org --app my-static-site \312 --source local \313 --runtime-mode static --static-dir dist --single-page-app \314 --build-command "deno task build" \315 --build-timeout 5 --build-memory-limit 1024 --region us316```317318## Environment Variables319320### Contexts321322Deno Deploy has three "contexts" - logical environments where your code runs, each with its own set of variables:323324| Context | Purpose |325|---------|---------|326| **Production** | Live traffic on your production URL |327| **Development** | Preview deployments and branch URLs |328| **Build** | Only available during the build process |329330You can set different values for the same variable in each context. For example, you might use a test database URL in Development and the real one in Production.331332### Predefined Variables333334These are automatically available in your code:335336| Variable | Description |337|----------|-------------|338| `DENO_DEPLOY` | Always `1` when running on Deno Deploy |339| `DENO_DEPLOYMENT_ID` | Unique ID for the current deployment |340| `DENO_DEPLOY_ORG_ID` | Your organization's ID |341| `DENO_DEPLOY_APP_ID` | Your application's ID |342| `CI` | Set to `1` during builds only |343344### Accessing Variables in Code345346```typescript347const dbUrl = Deno.env.get("DATABASE_URL");348const isDenoDeploy = Deno.env.get("DENO_DEPLOY") === "1";349```350351### Managing Variables via CLI352353```bash354# Add a plain text variable355deno deploy env add DATABASE_URL "postgres://..."356357# Add a secret variable (hidden after creation, only readable in code)358deno deploy env add API_KEY "sk-..." --secret359360# List all variables361deno deploy env list362363# Update just the value (keeps contexts and secret status)364deno deploy env update-value DATABASE_URL "postgres://new-url..."365366# Update which contexts a variable applies to367deno deploy env update-contexts DATABASE_URL production development368369# Delete a variable370deno deploy env delete DATABASE_URL371372# Load from .env file (all values treated as secrets by default)373deno deploy env load .env.production374375# Load from .env file, marking specific keys as non-secrets376deno deploy env load .env.production --non-secrets PUBLIC_URL APP_NAME377```378379### Variable Types380381- **Plain text** - Visible in the dashboard, good for feature flags and non-sensitive config382- **Secrets** - Hidden after creation, only readable in your code, use for API keys and credentials383384### Limits385386- Key names: max 128 bytes387- Values: max 16 KB388- Keys cannot start with `DENO_`, `LD_`, or `OTEL_`389390## Viewing Logs391392```bash393# Stream live logs394deno deploy logs395396# Filter by date range397deno deploy logs --start 2026-01-15 --end 2026-01-16398```399400## Databases & Storage401402Deno Deploy provides built-in database support with **automatic environment isolation**. Each environment (production, preview, branch) gets its own isolated database automatically.403404### Available Options405406| Engine | Use Case |407|--------|----------|408| **Deno KV** | Key-value storage, simple data, counters, sessions |409| **PostgreSQL** | Relational data, complex queries, existing Postgres apps |410411### Deno KV Quick Start412413No configuration needed - just use the built-in API:414415```typescript416const kv = await Deno.openKv();417418// Store data419await kv.set(["users", "alice"], { name: "Alice", role: "admin" });420421// Retrieve data422const user = await kv.get(["users", "alice"]);423console.log(user.value); // { name: "Alice", role: "admin" }424425// List by prefix426for await (const entry of kv.list({ prefix: ["users"] })) {427 console.log(entry.key, entry.value);428}429```430431Deno Deploy automatically connects to the correct database based on your environment.432433### PostgreSQL434435For PostgreSQL, Deno Deploy injects environment variables (`DATABASE_URL`, `PGHOST`, etc.) that most libraries detect automatically:436437```typescript438// Recommended: npm:pg (best PostgreSQL driver for Deno Deploy)439import pg from "npm:pg";440const pool = new pg.Pool(); // Reads DATABASE_URL from environment automatically441```442443### Provisioning444445Use the `deno deploy database` command to provision and manage databases:446447```bash448# Provision a Deno KV database449deno deploy database provision my-database --kind denokv450451# Provision a Prisma PostgreSQL database452deno deploy database provision my-database --kind prisma --region us-east-1453454# Assign to your app455deno deploy database assign my-database --app my-app456```457458For detailed CLI commands, see [Databases](references/DATABASES.md).459460### Local Development461462Use `--tunnel` to connect to your hosted development database locally:463464```bash465deno task --tunnel dev466```467468See [Databases](references/DATABASES.md) and [Deno KV](references/DENO_KV.md) for detailed documentation.469470## Local Development Tunnel471472The tunnel feature lets you expose your local development server to the internet. This is useful for:473474- **Testing webhooks** - Receive webhook callbacks from external services475- **Sharing with teammates** - Let others preview your local work476- **Mobile testing** - Access your local server from other devices477478### Basic Usage479480Add the `--tunnel` flag when running your app:481482```bash483deno run --tunnel -A main.ts484```485486The first time you run this, it will:4871. Ask you to authenticate with Deno Deploy (opens a browser)4882. Ask you to select which app to connect the tunnel to4893. Generate a public URL that forwards requests to your local server490491### Using with Tasks492493You can use `--tunnel` with your existing tasks in `deno.json`:494495```bash496deno task --tunnel dev497```498499This runs your `dev` task with the tunnel enabled.500501### What the Tunnel Provides502503Beyond just forwarding requests, the tunnel also:504505- **Syncs environment variables** - Variables set in your Deno Deploy app's "Local" context become available to your local process506- **Sends logs and metrics** - OpenTelemetry data goes to the Deno Deploy dashboard (filter with `context:local`)507- **Connects to databases** - Automatically connects to your assigned local development databases508509### Managing Tunnels510511- View active tunnels in the Deno Deploy dashboard under the "Tunnels" tab512- Stop a tunnel by terminating the Deno process (Ctrl+C)513514## Command Reference515516| Command | Purpose |517|---------|---------|518| `deno deploy --prod` | Deploy to production (app must exist first) |519| `deno deploy` | Preview deployment |520| `deno deploy create --org <name>` | Create new app (interactive) |521| `deno deploy create --org <name> --app <name> ...` | Create new app (non-interactive, see full flags above) |522| `deno deploy create ... --no-wait` | Create app without waiting for build to complete |523| `deno deploy create ... --allow-node-modules` | Create app including node_modules |524| `deno deploy env add <var> <value>` | Add plain text environment variable |525| `deno deploy env add <var> <value> --secret` | Add secret environment variable |526| `deno deploy env list` | List environment variables |527| `deno deploy env update-value <var> <value>` | Update variable value (keeps contexts/secret status) |528| `deno deploy env update-contexts <var> <contexts...>` | Update which contexts a variable applies to |529| `deno deploy env delete <var>` | Delete environment variable |530| `deno deploy env load <file>` | Load variables from .env file (defaults to secret) |531| `deno deploy env load <file> --non-secrets <keys...>` | Load .env file, marking specific keys as non-secrets |532| `deno deploy database provision <name> --kind <type>` | Provision a new database |533| `deno deploy database assign <name> --app <app>` | Assign database to an app |534| `deno deploy logs` | View deployment logs |535| `deno run --tunnel -A <file>` | Start local tunnel |536| `deno task --tunnel <task>` | Run task with tunnel |537538## Edge Runtime Notes539540Deno Deploy runs in one or many regions (globally distributed). Keep in mind:541542- **Environment variables** - Must be set via `deno deploy env`, not .env files at runtime543- **Global distribution** - Code runs at the region closest to users544- **Cold starts** - First request after idle may be slightly slower545546## Additional References547548- [Authentication](references/AUTHENTICATION.md) - Interactive and CI/CD authentication549- [Databases](references/DATABASES.md) - Database provisioning and connections550- [Deno KV](references/DENO_KV.md) - Key-value storage API and examples551- [Domains](references/DOMAINS.md) - Custom domains and SSL certificates552- [Frameworks](references/FRAMEWORKS.md) - Framework-specific deployment guides553- [Organizations](references/ORGANIZATIONS.md) - Managing orgs and members554- [Runtime](references/RUNTIME.md) - Lifecycle, cold starts, and limitations555- [Troubleshooting](references/TROUBLESHOOTING.md) - Common issues and solutions556557## Documentation558559- Official docs: https://docs.deno.com/deploy/560- CLI reference: https://docs.deno.com/runtime/reference/cli/deploy/561- Databases: https://docs.deno.com/deploy/reference/databases/562- Deno KV: https://docs.deno.com/deploy/reference/deno_kv/563- Domains: https://docs.deno.com/deploy/reference/domains/564- Environment variables & contexts: https://docs.deno.com/deploy/reference/env_vars_and_contexts/565- Organizations: https://docs.deno.com/deploy/reference/organizations/566- Runtime: https://docs.deno.com/deploy/reference/runtime/567- Tunnel: https://docs.deno.com/deploy/reference/tunnel/