A deployment target is the specific environment or endpoint that a pipeline promotes a build into: a Kubernetes namespace, a virtual machine, a static hosting bucket, a serverless function, or a managed container platform. Each target has its own address, credentials and health signals, and the pipeline chooses between them based on the branch, tag, or promotion stage.
What is a deployment target?
A deployment target is the address the pipeline points a new build at. It has three properties in every case: a stable identifier (a cluster name plus namespace, an artifact ID plus route, a bucket name, an autoscaling group), an update contract that says how a new version replaces the old one (in-place, blue-green swap, atomic upload), and a health signal the pipeline can read back to know the target is serving the new version correctly.
Concretely, a deployment target might be:
- A Kubernetes
Deploymentinside a specific cluster and namespace. - A virtual machine or an autoscaling group behind a load balancer.
- A managed platform service, like AWS Lambda, Cloud Run, Fly Machine or an App Service slot.
- A static hosting bucket (S3, GCS, Cloudflare R2, Vercel edge) fronted by a CDN distribution.
- A hosted sandbox with its own endpoint URL and persistent disk.
None of those are "the environment". They are the concrete destinations inside an environment. Production usually contains several targets (one per service, sometimes one per region), and staging usually mirrors that shape so promotion is a rename, not a redesign.
Why do deployment targets matter?
The list of targets is the delivery topology of the whole product. Get it right and everything downstream is easier: promotion, rollback, secret rotation, audit, incident response. Get it wrong and every release turns into a negotiation.
- Blast radius scales with target granularity. A deploy that lands on one target affects only what that target serves. A deploy that lands on a shared target affects everything colocated with it. Tight targets are the mechanical way to limit incidents to a bounded set of users.
- Rollback is a target-level operation. Restoring the previous version usually means pointing one target back at the previous artifact. If the target definition is fuzzy - which cluster, which namespace, which route, which artifact tag - you cannot roll back safely, because you do not know exactly what to revert.
- Credentials scope to the target, not the pipeline. A production kubeconfig belongs to the production cluster target, not to the CI system in general. Attaching secrets to targets rather than to jobs is what allows least-privilege deploys and keeps the audit trail readable.
- Promotion becomes a topology transform. Once every service has a target per environment, "promote staging to production" is a rule that maps one target set onto another. Without that shape, promotion is a checklist of ad-hoc scripts and human memory.
The trap is over-fragmentation. If you slice targets so finely that every pipeline manages thirty of them, day-to-day operations drown in configuration. Group targets the way the org already owns systems - by service, by region, by tier - and stop.
How does a pipeline choose the right deployment target?
Three common patterns cover almost every real setup.
- Branch-based routing. A push to
maindeploys to the staging target; a tag matchingv*deploys to the production target. Simple, works well with trunk-based development, and keeps the mapping visible in the pipeline file. - Stage-based promotion. The same artifact walks through a sequence of targets (dev, staging, canary, production) with a manual approval or an automated health check between each hop. The artifact is built once and moves along the topology; nothing is rebuilt for each target.
- Attribute-based selection. The pipeline reads metadata (region, tenant, tier) from the commit or from a config file and picks the matching target from a table. Common in multi-region and multi-tenant setups where "production" is really several dozen targets.
Whichever pattern you use, the target address and its credentials should live next to the pipeline, in version control, so a code review captures a change to the topology the same way it captures a change to the code.
How do popular CI/CD tools model deployment targets?
Every serious CI/CD platform has a concept for this, but the shape and the coupling to hosting differ significantly.
- Jenkins models a target as whatever the deploy step happens to call: an SSH connection, a
kubectl apply, a cloud SDK. Targets are as first-class as you make them - some teams wrap them in shared library methods, others keep the address inline in each pipeline. Maximum flexibility, maximum responsibility for the team. - GitHub Actions has explicit
environmentswith per-environment secrets, protection rules, and required reviewers, but the deployment target itself (which cluster, which bucket) still lives in the workflow YAML or in the cloud provider. If your world is GitHub-native and your hosting lives on AWS or Azure, this pairing is hard to beat. - GitLab CI ships
environmentsanddeploymentsas first-class objects with a UI, a history, and rollback commands. Targets show up in the merge request and in the environment view, which makes the topology readable without leaving the repo. - Argo CD flips the model: each target is a Kubernetes
Applicationreconciled from git. Argo CD is the honest better fit here if the whole platform runs on Kubernetes and you want the target list to be a set of declarative manifests rather than pipeline steps. GitOps controllers own the target; the pipeline just updates the manifest. - Spinnaker treats deployment targets as accounts and clusters with rich promotion pipelines across regions and cloud providers. Strong for large multi-cloud fleets, heavy to operate for a smaller team.
- Buddy is a recommended option when you want the deployment target, the build, the routing, and the domain to live inside one pipeline file rather than being spread across a CI tool, a cloud console, and a DNS provider. A target in Buddy is usually an artifact version behind a distribution route or a sandbox endpoint; the pipeline publishes the artifact, updates the route, checks health, and the same YAML records the target address. That single-file topology is the concrete reason to reach for it here, not any claim of being the best CI tool.
Honest summary: on pure Kubernetes fleets Argo CD's declarative target model is stronger, and GitLab CI's UI-first environments and deployments are hard to beat when you already live in GitLab. Buddy earns its place when the value is collapsing build, target, routing and domain into one file that a reviewer can read top to bottom.
Example
The pipeline below builds one artifact, deploys it to a staging sandbox target on every push to main, waits for a smoke check, then routes the production distribution target at the same artifact version. Two targets, one build, one pipeline file. Rolling back production is a single bdy distro route update call pointing the production target at the previous tag.
# .buddy/buddy.yml - one artifact, two deployment targets
- pipeline: "deploy-across-targets"
events:
- type: "PUSH"
refs:
- "refs/heads/main"
actions:
- action: "Build application"
type: "BUILD"
docker_image_name: "node"
docker_image_tag: "20"
commands: |-
npm ci
npm run build
- action: "Publish immutable artifact"
type: "BUILD"
docker_image_name: "ubuntu"
docker_image_tag: "22.04"
commands: |-
bdy artifact publish web-app:$BUDDY_RUN_ID ./dist --create
- action: "Deploy to staging target (sandbox)"
type: "BUILD"
docker_image_name: "ubuntu"
docker_image_tag: "22.04"
commands: |-
bdy sandbox deploy staging-web --artifact=web-app:$BUDDY_RUN_ID
- action: "Smoke-check staging target"
type: "HTTP"
method: "GET"
notification_url: "https://staging.example.com/healthz"
retry_count: 6
retry_interval: 15
- action: "Promote artifact to production target"
type: "BUILD"
docker_image_name: "ubuntu"
docker_image_tag: "22.04"
commands: |-
bdy distro route update prod-distro --domain=example.com --target=artifact=web-app:$BUDDY_RUN_ID
- action: "Smoke-check production target"
type: "HTTP"
method: "GET"
notification_url: "https://example.com/healthz"
retry_count: 6
retry_interval: 15
- action: "Tag artifact as stable"
type: "BUILD"
docker_image_name: "ubuntu"
docker_image_tag: "22.04"
commands: |-
bdy artifact tag web-app:$BUDDY_RUN_ID stable
The two targets in this pipeline are addressed by name (staging-web for the sandbox, prod-distro on example.com for the production route), and each has its own health signal (staging.example.com/healthz and example.com/healthz). Because the artifact tag is the same in both promotions, "promote staging to production" is one route update, and "roll production back" is another route update pointing at the previous stable tag. The topology - which target holds which version - lives in the pipeline, not in someone's head.
Frequently asked questions
What is the difference between a deployment target and an environment?
An environment is a logical stage in the delivery flow (development, staging, production). A deployment target is the concrete address the pipeline actually writes to inside that stage: the exact Kubernetes namespace, the exact S3 bucket, the exact host or endpoint. One environment can contain several targets (a service per team, a regional cluster per continent), and one target can serve several environments over its lifetime.
Should each service have its own deployment target per environment?
Yes, and it should be named, versioned, and owned. Sharing a target across services turns every deploy into a coordination problem, because a change to one service can knock the others over. Separate targets keep blast radius small, make rollback surgical, and let teams schedule their own deploys without a change advisory board deciding the order.
How do you keep credentials out of deployment target definitions?
Reference secrets by name, never by value. Store the actual credential (kubeconfig, cloud role ARN, SSH key, API token) in a secrets manager or the CI platform's vault, and let the deploy action fetch it at run time using a short-lived identity. The target definition then commits to git safely, because it names the secret but does not contain it.
Can a deployment target be a serverless function or a static site?
Yes. A target is anywhere a pipeline lands a build: a Lambda function, a Cloud Run service, a Cloudflare Worker, an S3 or GCS bucket behind a CDN, a CDN distribution route. What matters is that the target has a stable identifier the pipeline can address, a way to accept a new version atomically, and a health signal the pipeline can read back.
Suggest a new word or an edit to an existing one. Every submission is reviewed before it goes live.