---
title: "Unlimited Environments"
description:
  "Every Git branch is a full gateway environment on the same 300+ edge POPs as
  production. See practical implementation details and production tradeoffs."
canonicalUrl: "https://zuplo.com/features/unlimited-environments"
sourceUrl: "https://zuplo.com/features/unlimited-environments"
pageType: "feature"
generatedAt: "2026-09-04"
---

# Every branch is a full gateway environment

> Testing gateway changes against production is how outages happen — but real
> staging rarely feels worth standing up. With Zuplo, every branch becomes its
> own production-grade environment in seconds — included on every plan, even the
> free tier.

## Why this matters

Your team has one staging environment and seven branches fighting for it. When
testing a change is harder than shipping it, teams ship without testing. Real
per-PR environments are the cheapest reliability investment — but only if
they're free to spin up.

- **One staging environment, ten teams** — Whoever pushed last owns staging.
  Everyone else's testing is broken. The Slack channel for the booking system
  has been unreadable for months.
- **"Just test in prod"** — The infrastructure cost of a real per-feature
  environment makes "test it after the release" the default plan. Bugs ship.
  Customers find them.
- **Per-environment licensing math** — Some gateways charge per environment.
  Engineering managers who'd love a preview-per-PR can't justify the line item,
  so the experience tier sees "only main and staging" as the budget.
- **Helm-chart staging that takes 20 minutes** — A real "preview environment"
  elsewhere in the stack is a Terraform apply, a Helm chart, and a new DNS
  record. So you stop bothering. The gateway is the only thing left without
  preview.

## What you get

Vercel-style preview, applied to your gateway.

- **Every branch is a real, edge-deployed gateway** — Push a branch, get a URL.
  Same 300+ POPs as production. No cost, no provisioning, no waiting. Reviewers
  click the URL, run their suite, leave a comment.
- **Three stages, one model** — Production, Preview, Working Copy. Each has its
  own env-var scope. `ZUPLO_ENVIRONMENT_STAGE` tells your code which stage it's
  running in, so you can branch behavior cleanly without conditionals scattered
  across the repo.
- **Free, every plan** — Unlimited environments isn't a paid add-on. It's the
  default behavior on every Zuplo plan including the free tier. Every team's
  preview-per-PR ambitions stop hitting the budget conversation.

## One variable name, three scoped values

Define `DATABASE_URL` once with three values — Production points at your prod
cluster, Preview at staging, Working Copy at localhost.
`ZUPLO_ENVIRONMENT_STAGE` is populated automatically so your handler code can
branch behavior cleanly per environment.

```typescript
import { environment } from "@zuplo/runtime";

export default async function handler(
  request: ZuploRequest,
  context: ZuploContext,
) {
  // Same code, different behavior per environment
  if (environment.ZUPLO_ENVIRONMENT_STAGE === "production") {
    return forwardTo(environment.PROD_BACKEND);
  }
  if (environment.ZUPLO_ENVIRONMENT_STAGE === "preview") {
    return forwardTo(environment.STAGING_BACKEND);
  }
  // working-copy → local dev backend
  return forwardTo(environment.LOCAL_BACKEND);
}
```

```bash
# Variables defined once with stage-specific values:

DATABASE_URL  Prod      → postgres://prod.acme.co:5432
DATABASE_URL  Preview   → postgres://staging.acme.co:5432
DATABASE_URL  Working   → postgres://localhost:5432

STRIPE_KEY    Prod      → sk_live_…    (write-only secret)
STRIPE_KEY    Preview   → sk_test_…    (write-only secret)

# System variables populated automatically:
ZUPLO_ENVIRONMENT_STAGE  →  production | preview | working-copy
ZUPLO_ENVIRONMENT_NAME   →  acme-main-1235.zuplo.app
```

Highlights: Branch = Environment · Working Copy on `.zuplo.dev` · Per-stage
env-var scope · Different backends per env · Same 300+ edge POPs · Free tier,
unlimited envs.

## What makes Zuplo different

Real environments, not paid environments.

- **Branches IS environments** — Most gateways have an "environments" feature
  you have to manage separately from your code. Zuplo's environments come from
  your Git branches — they exist the moment you push, they share runtime with
  production, and they vanish when the branch is deleted.
- **Per-developer Working Copy** — Each developer has a personal cloud-hosted
  environment on a `.zuplo.dev` URL. Save in the portal, see the change live in
  seconds. No "who's using staging" question, no laptop-hostfile workaround.
- **Three env-var scopes, one variable name** — `DATABASE_URL` = production
  cluster in Prod, staging cluster in Preview, localhost in Working Copy. One
  variable, three values, scope-aware substitution. No `if (env === 'prod')`
  scattered throughout the codebase.
- **Edge runtime, not staging shims** — Preview environments run on the same
  300+ edge POPs as production. Latency, geography, and policy enforcement are
  identical to production — what works in preview works in prod, with no "oh
  that's staging behavior" surprises.

## What teams use this for

**"My PR touches the auth policy. How do I test it without breaking staging?"**
Push your branch. Hit the preview URL. The auth change runs on a real edge
environment with isolated env vars. Production is untouched, staging is
untouched, your reviewer has a real URL to test against.

**"We have 60 engineers and one staging slot."** Now you have 60 staging slots —
one per branch, each with its own URL. Each environment has its own preview
env-var scope, so secrets and config don't bleed across.

**"Our QA team needs an environment that lasts a sprint."** Create a long-lived
branch like `qa-sprint-42`. Merge feature branches into it instead of main. QA
hits a stable URL while features land. Merge `qa-sprint-42` into main when the
sprint ships.

**"The customer needs to validate v2 endpoints before we ship."** Send them the
`release/v2` branch URL. They get a real, edge-deployed v2 gateway scoped to
their access. No staging contention, no second cluster to maintain.

## FAQ

**How do I create separate environments for an API gateway?** Most teams need at
least three: production, staging, and per-developer working copies. With Zuplo,
every Git branch is automatically a real edge environment with its own URL —
production, staging, feature previews, hotfix branches, per-developer testing.
They all run on the same 300+ POPs as production, share the same routes and
policies, and only differ in their environment variables.

**How do API gateway preview environments work?** When you push a Git branch to
a Zuplo project, it deploys to a real edge environment at its own .zuplo.app URL
within 10–30 seconds. Reviewers can hit the live preview gateway, run
integration tests, or share the URL with QA. Merge the branch and the preview
goes away. No staging slot to fight for, no shared environment that breaks when
someone pushes.

**How do I run different config in dev, staging, and production?** Use
environment variables, scoped per stage. Each variable can be applied to
Production, Preview, or Working Copy independently — DATABASE_URL points at
prod-db.acme.com in Production, staging-db.acme.com in Preview, and localhost in
Working Copy. The gateway's TypeScript code reads the same env-var name
everywhere; the value swaps based on which environment is running.

**How do I share staging with multiple feature branches?** Create a long-lived
QA branch (e.g. qa-sprint-42) and merge feature branches into it instead of
main. QA hits a stable URL while individual features land. When the sprint
ships, merge the QA branch into main. Because every Git branch is a real edge
deployment, this pattern just works — no extra environment provisioning.

**Are unlimited preview environments included in the free tier?** Yes. Every Git
branch becomes a real preview environment on the same edge that runs production,
on every Zuplo plan including the free tier. Some customers run hundreds of
preview environments simultaneously. There's no per-environment line item or
per-environment licensing — environments are the workflow, not a billing
surface.

**Can preview environments use different backends than production?** Yes —
that's the whole point. Reference an env var like BASE_PATH in your route config
and set different values per environment. Production points at api.acme.com,
preview points at staging.acme.com, working copy points at
localhost.dev.acme.com. Same policy code, different origins, no special
branching logic.

**How is this different from environments in Apigee, AWS API Gateway, or APIM?**
Most legacy gateways treat environments as separate clusters or accounts you
provision in advance — pay-per-environment, slow to set up, capped by your
contract. Zuplo treats environments as branches — they exist the moment you
push, they share the same runtime, and they cost nothing extra. The mental model
is exactly Vercel or Netlify previews, applied to your API gateway.

**What's the best API gateway for preview environments and CI/CD?** Look for:
Git-branch-as-environment (no manual provisioning), real edge deployments per
branch (not staging shims), per-stage environment variables, fast deploy times,
and PR-comment integration so reviewers see preview URLs without leaving GitHub.
Zuplo combines all of these and is the only major gateway built for this
workflow from day one.

## Next steps

- Start a free account: https://portal.zuplo.com/signup
- Read the docs on environments: https://zuplo.com/docs/articles/environments
- See GitOps in action: /features/gitops
