---
title: "Unlimited Environments"
description:
  "Every Git branch is a full gateway environment on the same 300+ edge POPs as
  production. Three stages — Production, Preview, Working Copy — with isolated
  env vars per branch. Included on every plan, even the free tier."
canonicalUrl: "https://zuplo.com/features/unlimited-environments"
sourceUrl: "https://zuplo.com/features/unlimited-environments"
pageType: "feature"
generatedAt: "2026-10-08"
---

# 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.

Branches map to environments, for example:

| Branch              | Stage        | URL                           | Env vars | Key bucket   |
| ------------------- | ------------ | ----------------------------- | -------- | ------------ |
| main                | Production   | api.acme.com                  | 18       | prod-keys    |
| staging             | Preview      | staging.zuplo.app             | 18       | staging-keys |
| feature/billing-v2  | Preview      | feature-billing-v2.zuplo.app  | 18       | preview-keys |
| feature/auth-rework | Preview      | feature-auth-rework.zuplo.app | 19       | preview-keys |
| alice/working-copy  | Working Copy | alice-acme.zuplo.dev          | 17       | dev-keys     |

Every environment runs on 300+ edge POPs. `ZUPLO_ENVIRONMENT_STAGE` is
`production`, `preview`, or `working-copy`. Three stages (Production / Preview /
Working Copy), same edge, unlimited environments on 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.

## 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.

Stage-aware handler logic:

```ts
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);
}
```

Env vars scoped per stage:

```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 with
unlimited envs.

## 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.

## Frequently Asked Questions

### 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

Stop fighting for one staging slot — free Zuplo project, push a branch, watch a
real edge-deployed gateway appear at its own URL.

- [Start for Free](https://portal.zuplo.com/signup)
- [Read the Docs](https://zuplo.com/docs/articles/environments)
- [See GitOps in action](/features/gitops)
