Skip to content

    Apigee

    Apigee Environments, Revisions and Deployment

    How Apigee organizations, environments, groups and instances fit together, and how to deploy, configure, promote and roll back proxy revisions safely.

    By Published 16 min read

    Share

    This lesson is part of Apigee API Management: Beginner to Advanced. Enroll for free, then sign in, to read it in full.

    What you'll learn: How an Apigee organization, its environments, environment groups and instances route traffic to a proxy, how immutable revisions are deployed and rolled back, and how to keep one bundle running unchanged from dev to prod with per-environment configuration.

    Building a proxy is half the job. The other half is getting it to production repeatably, with the right backend in each stage, and being able to undo a bad release in minutes. Apigee gives you a small set of building blocks for this. If you understand how they relate, deployment stops being a ritual and becomes a routine.

    The core idea

    Think of a franchise restaurant chain. Head office writes one printed menu (the revision). The menu is identical in every restaurant, and you never pencil changes onto a printed copy: if the menu changes, head office prints a new edition. Each restaurant (an environment) has its own suppliers and prices on the wall (its target servers and key value maps), so the same menu works in the test kitchen and the flagship. The street address and the phone number customers use belong to a group of restaurants, not to a single dish (the environment group with its hostnames). And the building the kitchen sits in is a region-specific location (the instance).

    Four ideas to hold on to:

    1. A revision is immutable. Change means a new revision.
    2. A revision is deployed to an environment. Deployed means live; saved means not live.
    3. Anything that differs between environments lives outside the bundle.
    4. Promote the same revision up the chain. Never rebuild per stage.

    The hierarchy: organization, environment, group, instance

    Apigee organization, environments, environment group and instancesAPI clients to Load balancer (HTTPS); Load balancer to Environment group (into Apigee); Environment group to Environment prod; Environment group to Environment test; Environment prod to Instance in region A; Environment prod to Instance in region B; Environment test to Instance in region AAPIGEE ORGANIZATION (ONE GOOGLE CLOUD PROJECT)API clients: api.example.comAPI clientsapi.example.comLoad balancer: Google CloudLoad balancerGoogle CloudEnvironment group: hostnamesEnvironmentgrouphostnamesEnvironment prod: proxiesEnvironmentprodproxiesEnvironment test: proxiesEnvironmenttestproxiesInstance in region A: runtimeInstance inregion AruntimeInstance in region B: runtimeInstance inregion BruntimeHTTPSinto Apigee
    Hostnames belong to the environment group. Environments are attached to instances, which are regional runtimes.

    Read the diagram from left to right: a request reaches a load balancer you run in your own project, crosses into Apigee, is matched by hostname and base path to a proxy in an environment, and is served by the instance (a regional runtime) the environment is attached to. The pieces, as the Apigee documentation defines them:

    • Organization. The top-level container. When you create an organization for Apigee X, it maps to exactly one Google Cloud project, and a project holds at most one organization. It contains environments, API proxies, API products, apps and users. You can create more than one organization.
    • Environment. A place where proxies are deployed. A proxy must be deployed to an environment before anyone can call it. Names are 2 to 32 characters (lowercase letters, numbers and hyphens, starting with a letter) and cannot be changed after creation. On Pay-as-you-go you choose an environment type (Base, Intermediate or Comprehensive), which determines available features and cost; subscriptions always use Comprehensive.
    • Environment group (envgroup). The basic mechanism for routing requests to environments. Hostnames are defined on the group, not on the environment. Hostnames must be unique across all groups in the organization and cannot use wildcards; base paths must be unique within a group. An environment can belong to more than one group, and an environment that belongs to no group has no hostname and cannot be reached.
    • Instance. A region-specific runtime. Every environment must be attached to at least one instance, and there is one runtime instance per region.

    A request is made of a hostname, a base path (set on the proxy) and a resource. Environment and group names never appear in the URL. With a proxy whose base path is /catalog, a call to catalog.example.com/catalog/items goes to that proxy in whichever environment of the matching group has it deployed.

    How traffic reaches the runtime

    Apigee documents two networking models. In the non-peering model, Private Service Connect carries traffic both from clients to Apigee (northbound) and from Apigee to your backends (southbound): client requests pass through a global or regional external load balancer to a service attachment, a single point of attachment, and from there into Apigee. In the VPC peering model, Apigee connects to your network through private service access and peering, and each instance needs its own non-overlapping address ranges. Choose per the networking-options page; this affects how you reach private backends, not how environments or revisions work.

    Because of how routing works, one deployment can affect more than one group. An environment in two groups gets one address per group, and a new or removed base path can capture or redirect traffic for every group that contains the environment. Treat a deployment into a shared environment as a routing change, not only a code change.

    Revisions and deployment semantics

    Every time you save a proxy, Apigee creates a new numbered revision. A deployed revision is read-only; to change anything you create revision N+1 and deploy it. Deployment is all or nothing: the runtime deploys the whole bundle even if one policy changed.

    What the docs say about deploying:

    • One revision per proxy per environment. If another revision of the same proxy is already deployed, the REST override parameter (default false) decides what happens: with false the deployment is rejected, with true the new revision replaces the current one. The gcloud flag --override and the apigeecli flag --ovr do the same.
    • Successful deployments are zero-downtime. The new revision is sent to the runtime processors before the old one is undeployed.
    • Propagation is eventually consistent. Processors act independently, so deploying does not make the proxy available everywhere at the same instant.
    • A failed deployment is not a rollback. If a new revision fails to deploy, redeploy the previous revision to restore service; undeploying never restores a previously deployed revision by itself.
    • Routing changes can be sequenced. The sequencedRollout option rolls routing changes out in a safe order and matters mainly when a deployment takes traffic from another environment in a shared group or removes a base path. The generateDeployChangeReport API can show beforehand whether it is recommended.
    • Base path conflicts show a warning. In the UI a yellow indicator means some routing did not update because of a base path conflict.
    • Deployments count toward entitlements. A proxy deployment unit is one proxy or shared flow revision, per environment, per instance. One proxy in one environment attached to two instances counts as two units.
    • The deploy call can carry a service account. The serviceAccount parameter sets the proxy's Google identity, and the caller needs iam.serviceAccounts.actAs on it. This matters for logging and for calling Google services.
    sequenceDiagram participant CI as Engineer or pipeline participant API as Apigee management API participant RT as Runtime processors CI->>API: Import bundle as revision 4 API-->>CI: Revision 4 saved, not live CI->>API: Deploy revision 4 to prod with override API->>RT: Send revision 4 Note over RT: Processors sync independently RT-->>API: Revision 4 serving API->>RT: Undeploy revision 3 CI->>API: Check deployment status Note over CI: Error rate rises after release CI->>API: Deploy revision 3 to prod with override API->>RT: Revision 3 serving again API-->>CI: Rollback complete

    The diagram makes one point clear: rollback is just another deployment of an old, immutable revision, which is why it is fast and predictable.

    Per-environment configuration

    If the bundle must not change between environments, every difference has to live in the environment. Apigee offers two main places.

    Target servers. A target server is a named backend definition (host, port, protocol, optional TLS settings, and an isEnabled flag) that exists per environment. The TargetEndpoint refers to the name, so the same proxy points to different hosts in test and prod:

    <TargetEndpoint name="default">
      <HTTPTargetConnection>
        <LoadBalancer>
          <Server name="orders-backend"/>
        </LoadBalancer>
        <Path>/v1</Path>
      </HTTPTargetConnection>
    </TargetEndpoint>

    The <Path> element only applies when a LoadBalancer is used. Create the target server in each environment, with a different host each time:

    # Run once per environment, changing ENV and the host. The docs create an HTTPS
    # target by setting protocol "http", port 443 and sSLInfo.enabled true.
    curl -X POST \
      -H "Authorization: Bearer $(gcloud auth print-access-token)" \
      -H "Content-Type: application/json" \
      -d '{"name":"orders-backend","host":"orders.test.internal.example.com","protocol":"http","port":443,"isEnabled":true,"sSLInfo":{"enabled":true}}' \
      "https://apigee.googleapis.com/v1/organizations/$ORG/environments/ENV/targetservers"

    The same mechanism gives you rotation control: setting isEnabled to false takes a server out of load balancing. The same SSLInfo block configures TLS on a target server or a target endpoint; the docs do not say which wins if both are set, so define it in one place. A health monitor requires a non-zero MaxFailures, and retry needs at least two servers; the default MaxFailures of 0 means Apigee never removes a failing server from rotation.

    Key value maps (KVMs). Small configuration and secrets, read at runtime by the KeyValueMapOperations policy. KVMs have three scopes (API proxy, environment, organization); environment is the default, and the console UI manages environment-scoped maps only. Entries are encrypted, and a retrieved value should go into a variable whose name starts with private. so it never shows in Debug sessions. The scope in the policy must match the scope used when the map was created.

    <KeyValueMapOperations name="KVM-Get-Backend-Token" mapIdentifier="orders-config">
      <Scope>environment</Scope>
      <Get assignTo="private.backend.token">
        <Key>
          <Parameter>backend-token</Parameter>
        </Key>
      </Get>
    </KeyValueMapOperations>

    One behaviour to plan for: GET reads from an in-memory cache with a default expiry of 300 seconds, and the docs state that updating a KVM through the UI or API does not reset the cache. A changed value may therefore reach traffic only after the cache expires. Verify with a trace before declaring a config change live.

    Shared flows

    A shared flow is a reusable bundle of policies that proxies call with a FlowCallout policy. It is deployed to an environment like a proxy, and the shared flow must be deployed first, to the same environment as the proxy that uses it. If it is missing or not deployed, the FlowCallout fails at runtime with flow.SharedFlowNotFound. Some Apigee reference pages describe deploy-time dependency checks, but the documentation is not uniform on this, so treat "shared flow first" as the rule and do not rely on the deployment call to catch a missing one.

    Ways to deploy

    Method Good for Notes
    Console UI Learning, one-off fixes in non-prod Shows deployment status per revision with colour indicators; edits create revisions
    REST API Pipelines and custom tooling POST .../environments/ENV/apis/API/revisions/REV/deployments with an empty body; override, sequencedRollout, serviceAccount are query parameters
    gcloud Scripts on a machine with Google Cloud credentials gcloud apigee apis deploy REV --api=API --environment=ENV --organization=ORG --override; the revision defaults to latest
    apigeecli Importing bundles and deploying from CI Open source and not an officially supported Google product; flags such as -e, -n, -v, --ovr, --wait
    # Zip the bundle, import it (creates a new revision) and deploy it to dev in one step.
    zip -r orders-v1.zip apiproxy
    apigeecli apis create bundle -n orders-v1 -p orders-v1.zip -e dev --ovr --wait -o "$ORG" -t "$TOKEN"
    
    # Promote an existing revision to test, then prod.
    apigeecli apis deploy -n orders-v1 -e test -v 3 --ovr --wait -o "$ORG" -t "$TOKEN"
    apigeecli apis deploy -n orders-v1 -e prod -v 3 --ovr --wait -o "$ORG" -t "$TOKEN"
    
    # Undeploy a revision from an environment.
    apigeecli apis undeploy -n orders-v1 -e dev -v 3 -o "$ORG" -t "$TOKEN"

    By default apigeecli apis deploy runs a generateDeployChangeReport check first (--safedeploy) and proceeds only if there are no conflicts. The next lesson on CI/CD wires these commands into a pipeline.

    How to implement it step by step

    You will take a proxy orders-v1 from dev to test to prod with a different backend in each, then roll back.

    Step 1: create or choose the environments. In the console open Apigee > Management > Environments and click Create Environment, or call the environments API. Attach each environment to an instance (an environment with no instance serves nothing) and to an environment group (an environment with no group has no hostname). On Pay-as-you-go, charges for an environment start once it is attached to an instance, even before traffic arrives.

    Step 2: define the same target server name in every environment, with the host that belongs there, using the call above. The proxy only knows orders-backend.

    Step 3: create environment-scoped KVMs for anything else that differs (feature switches, non-secret settings, tokens) and read them with KeyValueMapOperations. Keep secrets out of the bundle.

    Step 4: build once and deploy to dev. Import the bundle, which creates a revision, and deploy it to dev. Run integration tests against the dev hostname.

    Step 5: promote the same revision. Deploy revision 3 to test, run contract tests, then deploy revision 3 to prod and run a smoke test. Never rebuild the bundle between steps.

    Step 6: change configuration without touching the bundle. To point test at a new backend, update the orders-backend target server in test, or edit the environment KVM entry. No new revision, no redeployment. After a KVM edit, wait for the cache expiry (default 300 seconds) or confirm in a debug session.

    Step 7: roll back. If revision 4 misbehaves in prod, redeploy revision 3 with override:

    gcloud apigee apis deploy 3 --api=orders-v1 --environment=prod --organization="$ORG" --override

    Then check the deployment status in the UI (green means no errors or warnings) or through the deployments API, and confirm with a request. Record which revision is live so the next person knows.

    flowchart LR B[Build bundle once] --> R[Revision 3 saved] R --> D[Deploy to dev] D --> DT[Integration tests] DT --> T[Promote same revision to test] T --> TT[Contract tests] TT --> P[Promote same revision to prod] P --> PT[Smoke test and watch dashboards] PT --> RB{Healthy?} RB -- no --> RO[Redeploy previous revision with override] RB -- yes --> DONE[Release complete] CFG[Target servers and KVMs per environment] -.-> D CFG -.-> T CFG -.-> P

    Choosing an environment layout

    The most common design question is how many organizations and environments to create. The facts that drive it: an organization is one Google Cloud project; API products, apps, developers and users are organization-level; environments are the unit of deployment and of per-environment configuration. You can create more than one organization (with Pay-as-you-go there is no fee for creating one).

    Layout Strengths Costs and risks
    One org, several environments (dev, test, prod) Simplest; one place for products, developers and apps; promotion is a deployment to another environment Environments share organization-level resources, so a mistake with a product or app is visible everywhere; one project's IAM and quota boundary
    Two orgs: non-prod and prod Hard separation of IAM, billing and quotas between prod and the rest; non-prod can be loose Products, developers and apps must be recreated in each org, ideally by automation; two sets of setup to maintain
    Org per team or per developer community Independent ownership and portals, as the docs describe for different communities Duplicated governance; cross-org consistency is your job
    flowchart TD S[Choosing a layout] --> Q1{Must prod be isolated from non-prod by IAM, billing or quota?} Q1 -- yes --> O2[Separate prod and non-prod organizations; automate product and app setup] Q1 -- no --> Q2{Different teams or developer communities with separate ownership?} Q2 -- yes --> O3[One organization per team or community] Q2 -- no --> O1[One organization with dev, test and prod environments] O1 --> Q3{Clients in more than one region?} O2 --> Q3 O3 --> Q3 Q3 -- yes --> M[Attach environments to instances in each region] Q3 -- no --> E[One instance is enough]

    Whatever you choose, give each environment its own environment group only if it needs its own hostname; sharing a group between environments means their base paths must not collide.

    Use cases

    1. Promoting dev to prod with different backends. The proxy calls the target server orders-backend. In dev it points to a mock service, in test to a staging system, in prod to the real one. Promotion is deploy revision 3 to the next environment; the host change lives entirely in each environment's target server.

    2. Blue/green style revision switch. Apigee keeps one deployed revision per proxy per environment, so two revisions cannot be live side by side in one environment. You can still get a blue/green effect using documented pieces: run the old and new backends as two target servers, listed in the proxy's LoadBalancer, and flip their isEnabled flags to move traffic with no new deployment; or deploy the new version as a separate proxy with its own base path and switch clients by DNS or hostname. Confirm in a debug session how quickly the flip takes effect before you rely on it for a release.

    3. Regional or multi-instance setups. To serve another region, create a new instance there (one instance per region), then attach the existing environments to it, one attachment call per environment. The docs warn against creating a separate environment with the same base paths and hosts, which can cause HTTP 503 errors at runtime. Environment groups need no change because environments stay in them. Evaluation organizations are limited to one region, adding a region depends on your licence entitlements, and a deployment unit is counted per environment, per instance.

    4. Hotfix. A prod bug is fixed in revision 5. Import it, deploy to test for a quick check, deploy the same revision to prod. If the check fails, redeploy revision 3. No environment-specific rebuild.

    A short note on hybrid

    Apigee hybrid keeps the same model of organizations, environments and environment groups, but splits the product: Google hosts the management plane, and you run the runtime plane on Kubernetes you operate. The difference is that you also install, configure and operate the runtime on your own cluster. Check the version-specific hybrid docs before acting (for example on environment groups in the runtime configuration), because hybrid is versioned and these pages differ from Apigee X.

    In practice: promoting an orders API from dev to prod

    NOTE

    A realistic scenario, not a case history. This is a composite example built from common production patterns. It does not describe any specific company, and every number in it is an illustrative assumption.

    The situation. A team edits the orders-v1 proxy directly in the production organization's UI. Twice, a change that worked in test failed in prod because the backend host was hard-coded into the bundle. Nobody can say which revision is live, and a rollback means re-typing old policy settings.

    Starting architecture.

    Before: one proxy edited by hand, with the backend URL inside the bundleEngineer to Apigee prod environment (edit and deploy); Apigee prod environment to Orders backendEngineer: edits in the UIEngineeredits in the UIApigee prod environment: revision unknownApigee prodenvironmentrevision unknownOrders backend: host baked inOrders backendhost baked inedit and deploy

    What changes.

    1. Create dev, test and prod environments in the organization and attach each to an instance and a group.
    2. Replace the hard-coded URL with the target server orders-backend, defined in each environment with its own host.
    3. Move per-environment settings into environment KVMs read with KeyValueMapOperations.
    4. Build the bundle once, deploy revision 3 to dev, then promote the same revision to test and prod with apigeecli apis deploy ... --ovr --wait.
    5. Write down the rollback command: redeploy the previous revision with override.

    Result. The bundle that passed tests is byte-for-byte the one running in prod; only the target server differs. The team can state the live revision per environment, and a bad release is undone by redeploying the previous revision rather than by editing policies under pressure.

    Architect's notes

    • Environments are cheap to reason about, not free. On Pay-as-you-go, charges start when an environment is attached to an instance. Do not create one per feature branch.
    • Treat deployment as a routing change in shared groups. Base-path collisions and removals affect everyone in the group; use the change report and sequenced rollout when a deployment moves traffic between environments.
    • Prefer target servers over KVMs for hostnames. They are first-class backend definitions with enable/disable, load balancing and TLS settings. Use KVMs for small values and secrets.
    • Know your cache. KVM reads are cached. Design operational changes (a kill switch, a flag) with the cache expiry in mind, or use a mechanism that takes effect immediately for the case you care about.
    • Automate org-level setup in a two-org layout. Products, developers and apps are not shared between organizations. Script them so non-prod and prod do not drift.
    • Do not edit in prod. Everything deployable is code in version control, and the pipeline is the only thing that deploys.
    • Check quotas and limits. Apigee recommends no more than 3,000 base paths per environment or environment group, and the Limits documentation lists API call rates and deployments per instance. Check it for current numbers.

    Common mistakes

    • Hard-coding the backend in the bundle. Use target servers and KVMs so the same revision runs everywhere.
    • Rebuilding per environment. It makes "works in test, not in prod" unfalsifiable. Promote the same revision.
    • Forgetting override. Deploying a new revision when one is live is rejected unless override is set.
    • Assuming undeploy rolls back. It does not. Redeploy the previous revision explicitly.
    • Deploying a proxy before its shared flow. Deploy shared flows first, to the same environment.
    • Environment with no group or no instance. It has no hostname, or nothing to run on, so calls fail. Attach both.
    • Overlapping base paths in a group. A deployment can capture another proxy's traffic. Keep base paths unique per group.
    • Expecting an instant KVM change. The read cache means a changed value may take minutes to reach traffic.
    • Putting secrets in the bundle. Use encrypted KVMs or a secret manager.

    Key takeaways

    • An organization maps to one Google Cloud project and contains environments; hostnames live on environment groups; instances are regional runtimes.
    • An environment needs a group to be reachable and an instance to serve traffic.
    • Revisions are immutable; deploy one revision per proxy per environment, with override to replace a live one.
    • Successful deployments are zero-downtime, but propagation is eventually consistent; verify after deploying.
    • Rollback is redeploying the previous revision; undeploy alone does not restore it.
    • Keep environment differences in target servers and KVMs so the same bundle is promoted dev to prod.
    • Deploy shared flows before the proxies that call them, into the same environment.
    • Pick the organization layout by isolation needs, and automate organization-level objects if you split them.

    Practice exercises

    Starter (about 30 minutes). In an evaluation organization, create an environment, attach it to an instance and a group, deploy any sample proxy, and call it through the group's hostname. Note the deployment status indicator and what happens when you deploy a second revision with and without override.

    Intermediate (about 2 hours). Create dev and test environments. Define orders-backend target servers pointing to two different public sample services, deploy one bundle to both, and prove each environment calls its own backend. Add an environment KVM value and read it with KeyValueMapOperations into a private. variable. Change the KVM and measure how long the change takes to appear. Then roll back by redeploying the previous revision.

    Advanced (half a day). Script the full promotion with apigeecli or gcloud plus the REST API: import, deploy to dev, run a test, promote the same revision, and roll back on a failed check. Write a one-page decision record for your organization layout using the flowchart in this lesson, and list the organization-level objects you would need to script if you used two organizations. Add a second instance in another region in an evaluation or sandbox organization if your entitlement allows, and document the attachment calls.

    Official documentation

    Enroll to keep reading

    Lesson 8 of 11 · Apigee API Management: Beginner to Advanced

    How Apigee organizations, environments, groups and instances fit together, and how to deploy, configure, promote and roll back proxy revisions safely.

    In the rest of this lesson

    • Ways to deploy
    • How to implement it step by step
    • Choosing an environment layout
    • Use cases
    • A short note on hybrid
    • In practice: promoting an orders API from dev to prod

    Enrolling is free. It unlocks every lesson in Apigee API Management: Beginner to Advanced, tracks your progress across devices and keeps your quiz scores. The newsletter is optional.

    Ask about this article

    Get answers grounded in this post. AI-generated — based on this article, and may be imperfect.

    Scaled AI Weekly

    Enjoyed this? Get more like it every Monday.

    Real architecture decisions, LLMOps patterns that survive production, and engineering leadership advice — from 12+ years of building at enterprise scale. Free. No spam. Unsubscribe anytime.

    Get new articles by email

    Free. We email a confirmation link first, and you can unsubscribe from any email.

    Join engineers building production AI systems

    Comments