How releases work
Every time you merge a PR to develop, you are not just merging code — you are setting off an automated chain that can put your change in front of 45 million users the same day. Understanding how this works helps you make better decisions about what to merge, when, and how to monitor your changes after they ship.
The core idea: one branch, all channels
Postman ships the same codebase to multiple named "channels" — different versions of the app with different configurations. All of them come from the same place: the develop branch.
When you merge to develop, your code automatically flows through this pipeline:
Your PR merged to develop
↓
Automated daily build (CI/CD)
↓
├── dev channel → team uses this internally
├── beta channel → users who opted in to beta
├── canary channel → early adopters, latest code
├── stage channel → QA and security review
└── prod channel → everyone (45M+ users)
There is no separate release branch. No manual "cherry-pick to production." If it's on develop and passes CI, it will ship.
This is why the contribution guidelines say: anything merged to develop must be production-ready. Because it will be in production — soon.
What are channels?
Each channel is a different build of the app. Think of them like different rings of confidence:
dev — Built on every commit to develop. This is what the engineering team uses internally for day-to-day development. It points to the dev backend and has extra debugging enabled.
beta — A daily build that opt-in users get. People who choose "Beta" in their Postman settings. A few hundred thousand users. It's the first external validation of new features.
canary — Similar to beta, but even more frequent. Users who want the absolute latest, who accept the risk of rough edges. Canary builds are the team's early warning system for serious regressions.
stage — A controlled environment for QA and security teams. Before a production release is made, it goes through stage. Security reviews happen here. Major bugs found here don't reach production.
prod — The stable release. What most users are running. It only moves when the team is confident. When it does move, the auto-updater delivers it silently to all users over the following days.
The channel configuration — app name, icons, backend URLs, deep-link protocol — is defined in starship/:
starship/
├── dev.json → PostmanDev, dev backend, postman-dev:// protocol
├── beta.json → PostmanBeta, beta backend
├── canary.json → PostmanCanary, production backend
├── stage.json → PostmanStage, stage backend
└── prod.json → Postman, production backend
The CI/CD pipeline: what happens when you push a PR
Before your code can reach any channel, it must pass the Pre-Integration check. This runs automatically the moment you push a branch.
PR opened
↓
Pre-Integration runs (currently ~7-11 minutes):
├─ ─ Code formatting (Prettier — only changed files)
├── ESLint (only affected packages via nx affected)
├── TypeScript typecheck (only affected packages)
├── Unit tests (only affected packages via nx affected)
├── Bundle size check (Statoscope — fails if critical path +5kB)
└── Circular dependency check
↓
All green? → PR can be merged
Failed? → Fix the issue, don't disable the check
The key innovation here is nx affected. Instead of running every test in the entire codebase on every PR, CI builds a graph of what changed and what depends on it — and only tests those packages. This is what keeps CI fast even with 250+ packages.
The team is working to get pre-integration under 5 minutes by December 2026. The main remaining work: finishing the Jest → Vitest migration across all packages, upgrading to TypeScript v7 (10x faster typechecking), and upgrading to Rspack v2 (20% faster builds). Tracked in CBR-504.
How the daily release works
Once code is on develop, an automated daily release job packages and ships it:
develop branch (nightly, automated)
↓
Build all targets:
├── Desktop build (Electron, macOS + Windows + Linux)
└── Web build (browser app)
↓
Starship packaging — creates binaries per channel
↓
Distribute:
├── Upload desktop binaries to hosting
├── Push web build to CDN
└── Notify the auto-updater
↓
Users get the update silently via auto-updater
This pipeline was redesigned in 2025 when the team migrated from CircleCI to GitHub Actions. The migration saved $1,000,000/year in CI infrastructure costs and made production releases happen daily instead of weekly.
How a user gets the update
Postman uses Electron's built-in auto-updater. When a new production release is published:
- The app checks for updates in the background (on startup, and periodically)
- If an update is available, it downloads silently
- On the next restart, the new version launches
- Users don't notice — they just have a newer version
There is no "update button" users need to click for most releases. It just happens. This is why breaking changes need to be backward-compatible and feature-flagged: you cannot predict exactly when a user will actually run the new code.
Feature flags
Some features are too risky to ship to everyone at once. For those, postman-app uses feature flags via Amplitude (an internal experiment platform).
A feature flag lets you ship the code to production but control who can actually see and use it:
import { useFeatureFlag } from '@postman-app/amplitude';
export const WorkspaceActivityFeed = () => {
const isActivityFeedEnabled = useFeatureFlag('activity_feed_v1');
if (!isActivityFeedEnabled) return null;
return <ActivityFeedWidget />;
};
With this pattern, you can:
- Ship to dev/beta first, validate it works, then gradually roll out to prod
- Enable it for specific users or teams for testing
- Kill-switch a feature instantly if something goes wrong in production
Feature flags are especially important for anything that touches the critical path (app startup, request sending, collection loading).
The hotfix path
When something breaks in production and can't wait for the next daily release:
# Branch from develop (not a release branch — develop is what ships)
git checkout -b fix/hotfix-JIRA-ID-description
# Fix the issue, write the RCA, write a regression test
# PR titled: [HOTFIX][JIRA-ID] description
# Tag the team lead for expedited review
# After merge to develop, coordinate with the release team
# for an out-of-cycle production build
Hotfixes are rare because the automated daily release + feature flags mean most issues can be handled without breaking the normal flow.
What you should do after your code ships
Just because your PR merged doesn't mean your job is done. Here's what to watch for:
Monitor the beta/canary channels. Your code is live for opt-in users within 24 hours of merging. Watch your Slack channels and Jira for any reports of issues in beta.
Check the error monitoring. The team uses New Relic for error tracking. After a significant change, check that error rates haven't spiked.
Update your Jira ticket. Mark it "In Stage" when the code freeze happens. Mark it "Done" when the production release ships.
Write a regression test. If your change was a bug fix, write a test that would have caught it. This is one of the most valuable things you can do for the codebase.
The build system: Rspack + SWC
For completeness: the actual bundling is done by Rspack with SWC as the transpiler (replacing Webpack + Babel). The evolution:
| Era | Bundler | P95 build time |
|---|---|---|
| 2022 | Webpack 4 | 29 seconds |
| 2023 | Webpack 5 | 16 seconds |
| 2024+ | Rspack + SWC | 5 seconds |
This 6x improvement came from Patrick Sevat's work on the build tooling. Rspack is a Rust-based Webpack-compatible bundler that can use the same configuration — which meant migration was incremental rather than a big-bang rewrite.
References
All content on this page is synthesized from:
- Plan and vision for Continuous Integration for 2026 — Opi Danihelka
- CI under 5 minutes — Opi Danihelka
- Vision for Postman App Development — Patrick Sevat
- App contribution guidelines — Client Foundation team
- postman-app README