Using Travis CI Build Stages to Parallelize Jobs and Gate Deployments
Learn how to structure .travis.yml with named stages so independent jobs run in parallel while deployment waits for all prior stages to succeed.
09 Feb 2026, 12:37 UTC

The problem: slow feedback and risky deployments
When a Travis CI build runs linting, unit tests, and integration tests one after another, you waste minutes waiting for each step to finish before the next can start. At the same time, you want to be certain that a deployment only happens after every test has passed, but you also don’t want to delay feedback on independent checks.
Thesis: Build Stages give you parallelism inside a stage and sequential gating between stages
Travis CI’s Build Stages feature lets you declare named stages in .travis.yml. All jobs assigned to the same stage are triggered concurrently (subject to your account’s concurrency limits), while the next stage begins only after every job in the current stage finishes successfully. This model lets you parallelize independent work and still enforce a hard gate before deployment.
How to define stages in .travis.yml
Add a top‑level stages: list that names each stage in the order you want them to run. Then, for each job, set the stage: key to match one of those names. Jobs without an explicit stage default to the built‑in test stage.
# .travis.yml
stages:
- lint
- test
- deploy
jobs:
include:
- stage: lint
name: "ESLint linting"
script: npm run lint
- stage: test
name: "Unit tests"
script: npm test
- stage: test
name: "Integration tests"
script: npm run test:integration
- stage: deploy
name: "Deploy to staging"
script: ./deploy.sh
# Deployment only runs if lint and test stages succeed
In this example:
- The
lintstage has a single job, so it runs alone. - The
teststage contains two jobs (unit and integration tests). Travis starts them at the same time, giving you faster feedback on both. - The
deploystage waits until both test jobs finish without error before it begins.
Verifying that stages work as expected
- Commit the
.travis.ymlabove to a repository linked to Travis CI and push to the default branch. - Open the build page on Travis CI. You should see three distinct blocks labeled “lint”, “test”, and “deploy”.
- Click into the “test” block and examine the logs. The timestamps for the unit and integration test jobs should overlap, confirming they ran in parallel.
- Check that the “deploy” block does not start until the “test” block shows a green (passed) state for both jobs.
To confirm the gating behavior, intentionally make the unit test job fail (e.g., change npm test to exit 1) and push again. You will see the “deploy” block skipped entirely. If you want a job to be allowed to fail without stopping later stages, add allow_failure: true to that job definition.
Trade‑offs and limitations
- Stage name rules: Names must be unique and cannot contain special characters (only alphanumerics, underscores, and hyphens). Avoid generic names like
buildif you have legacy configurations that rely on the default stage. - Failure propagation: By default, any failed job in an earlier stage skips all later stages. This is safe for deployment gating but can hide intermittent problems if you misuse
allow_failure: true. - Concurrency limits: The number of jobs that can run simultaneously is limited by your Travis CI plan (including the free tier). If you exceed the limit, some jobs will queue, reducing the parallel speed‑up.
Actionable next steps
Start small: add a two‑stage configuration (e.g., test and deploy) to an existing .travis.yml, push, and watch the build page for the stage blocks. Once you’re comfortable, split your test suite into logical groups (lint, unit, integration) and assign them to the same stage to gain parallel feedback. Monitor your build minutes to ensure you stay within your plan’s concurrency limits, and adjust the stage boundaries if you notice jobs waiting for resources.
By structuring your CI pipeline with Build Stages, you get faster feedback on independent checks while keeping a reliable gate before any code reaches production.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.