Data flow & caching
When you open a workspace in Postman and see your collections, environments, and requests appear on screen, data traveled through multiple layers — some from memory, some from disk, some from the network. This page explains the complete journey, every caching layer, and how the two modes (cloud vs local) differ.
The storage layers
postman-app has five distinct places where data can live:
| Layer | Technology | Survives reload? | Where |
|---|---|---|---|
| React Query cache | TanStack Query | No (in-memory) | Browser memory |
| Zustand/MobX stores | Zustand / MobX | No (in-memory) | Browser memory |
| IndexedDB cache | Dexie (via storage-sdk) | Yes | Browser storage |
| Local filesystem | YAML/JSON files | Yes | Your disk (desktop) |
| OPFS | Origin Private File System | Yes | Browser storage |
| Bifrost backend | Postman's servers | Yes | Postman's cloud |
End-to-end flow: opening a workspace (cloud mode)
This is what happens when you navigate to a workspace. Every step, in order:
The key insight: The user sees data from IndexedDB immediately, while the fresh data loads in the background. No loading spinner on return visits. This is the "stale-while-revalidate" pattern.
The two-phase fetch: how caching is populated
When the app first fetches a list of environments or collections, it doesn't wait to load every item fully before showing anything. It uses a two-phase approach:
This is why the sidebar appears quickly — names load first, then the full content. You might notice environments show names before the variable values are available. That's Phase 1 vs Phase 2.
Real-time updates via WebSocket
HTTP fetches get you the initial data. But Postman is collaborative — when a teammate adds a collection, you see it appear without refreshing. That's the WebSocket sync:
The realtime-pubsub package manages subscriptions efficiently — if 10 components on screen all care about the same workspace's collections, they share a single WebSocket subscription, not 10 separate ones. The package reference-counts subscriptions and tears down the server-side subscription when the last consumer unmounts.
Cloud mode vs local mode
Postman supports two workspace modes. The data layer handles both with the same Service interface — the code above the service layer doesn't know or care which mode it's using.
Cloud mode: Collections, environments, and workspace data live on Postman's servers. Fetched via HTTP through Bifrost. Updated in real time via WebSocket.
Local mode (desktop): Everything is YAML/JSON files on your disk. The app reads from and writes to the filesystem via IPC. A file watcher (platform-libs/filesystem-watcher) monitors for external changes (like a git pull) and updates the UI automatically.
Local mode (browser): Same concept as desktop local mode, but uses OPFS (Origin Private File System) — a virtual filesystem inside the browser — instead of the native filesystem.
The IndexedDB structure
IndexedDB is the persistent client-side cache. It uses Dexie as an ORM, provided by platform-libs/storage-sdk.
Key design decisions:
-
One database per user × workspace × mode.
${userId}-${workspaceId}::cloud-environmentsis a separate Dexie database from${userId}-${workspaceId}::local-environments. This prevents cross-workspace data leaks and allows independent clearing. -
IndexedDB is a projection, not the source of truth. You never read from IndexedDB for normal operations. It's written to during fetches. It's read only on startup for cache hydration. The backend is always the authority.
-
Encryption is optional.
storage-sdksupports encrypting stored values with a custom key. Environment variable values (which can contain API keys and secrets) are candidates for this.
What happens on startup (the full sequence)
When Postman starts and you return to a workspace you've visited before:
The experience from the user's perspective: content appears immediately (from IndexedDB), then silently updates to the latest version. No loading spinner on return visits.
Summary: which cache layer answers the question?
| Scenario | Data comes from |
|---|---|
| First time opening a workspace (no cache) | Bifrost API |
| Returning to a workspace (same session) | React Query in-memory cache |
| Returning to a workspace (after app restart) | IndexedDB hydration → then API re-fetch |
| Collaborator makes a change | WebSocket event → React Query cache invalidation → API re-fetch |
| Editing a local workspace (desktop) | Filesystem via IPC |
| Editing a local workspace (browser) | OPFS |
| User logs in on a new machine | Bifrost API (no local cache) |
References
data/environment-data/src/experimental/idb/README.md— detailed IndexedDB cache architectureplatform-libs/storage-sdk/README.md— the IndexedDB wrapper with encryption and migrationsplatform-libs/realtime-pubsub/README.md— WebSocket pub/sub with ref-countingplatform-libs/workspace-opfs/ARCHITECTURE.md— OPFS for browser local workspacesplatform-libs/react-query-utils/README.md— React Query integration patterns and persistencedata/collection-data/src/services/README.md— Cloud vs Local service implementations