Bundle Diffing (bsdiff) & Content Addressable Storage
- Server
- Dashboard
- eoas CLI
Highlights
Bundle Diffing (bsdiff) (PR #206)
We're happy to announce that Bundle Diffing is now supported by xprem.
Bundle diffing lets devices download a small bsdiff patch instead of the full JavaScript bundle when they already have a previous update, then rebuild the new bundle locally.

Scope and activation
- Only available in control plane mode (database mode).
- Only works for updates published from version 3.2.0
- Off by default. Enable it with
BUNDLE_DIFFING=true.
Please see the full documentation: here.
If you want to learn more about Bundle diffing & bsdiff please take a look at this blog post.
Content Addressable Storage (PR #198)
Until v3.2.0, xprem used a storage model that started to reach its limits:
Since the beginning of the project, we have historically stored update files (assets + bundle) in the bucket under the following format:
:appId/:branchName/:runtimeVersion/:updateId/{bundle + asset files}
Problems with this model
- Wasted storage: Assets are redundant and duplicated in every update folder
- Poor CDN caching: The asset cache does not survive between two updates, even when the assets are identical
To solve this problem, we implemented the following changes:
- Updates (Assets + JavaScript Bundle) are no longer stored in the update folders but in a new folder
:appId/cas/{SHA256} - This sha256 hash is computed by the client for each file during
eoas publish - Asset deduplication is done through a lookup by hash in the blob store (database in stateful mode, bucket in stateless mode)
- The update idempotency check is now performed at the
/requestUploadUrllevel, since the hash values are now known "before" the/markUpdateAsUploaded.
These changes will drastically reduce bucket size and update publication times, and reduce /manifest computation times: asset hashes are the CAS keys, so the server no longer needs to read and hash the files when composing the manifest. Finally, CDN caching is preserved for assets that are unchanged across updates.
The configuration files update-metadata.json (stateless mode), expoConfig.json and metadata.json are still stored in the update folders.
This change is backward compatible. Updates published before the new storage model was introduced will continue to be supported.
Import existing Expo Application from EAS (PR #197)
It's now possible to import an existing Expo app directly from EAS using an access token.
The import will:
- Creates an app while preserving the Expo UUID
- Syncs branches and channels, preserving their mapping
- Syncs update history, re-signing assets and bundles along the way

Link updates to source repositories (PR #209)
It's now possible to attach a git repository URL (e.g. github.com/user/repo) to an app in the App Info section of the dashboard. Once set:
- Commit hashes link directly to their source commit.
- `#123` references in update message link to pull requests on GitHub, Bitbucket and Cursor Origin.
- `!123` references in update message link to merge requests on GitLab.

