It's surprisingly easy to inflate your build artifacts without noticing. Perhaps you added a simple date formatter and included moment.js
, inadvertently adding hundreds of kilobytes to your JavaScript bundle. Or you shipped a 16MB JPEG to your website where a small thumbnail weighing in at a few KB would have be sufficient. Maybe a new dependency in your Rust project increased your CLI tool's size by several megabytes for very little added value. These small changes accumulate, impacting performance, user experience, and leading to unnecessary computation or data transfer and storage costs.
We've seen this over and over across the numerous projects we worked on over the years. Innocuous code changes can significantly increase artifact sizes, often going unnoticed because there's no way to see these implications during a pull request review. That's why we created Gravity, a tool that visualizes a PR's impact on artifact sizes within the CI pipeline. It supports all kinds of artifacts, from JS bundles and images to binaries and Docker images–anything where your care about the size of your artifacts."
anchorHow does Gravity work?
Inspired by visual regression testing tools like Percy and Chromatic, Gravity integrates seamlessly into the developer workflow:
- Gravity analyzes production build artifacts for every CI run.
- For each new pull request, Gravity compares the artifacts generated by the PR against those from the target branch. If it detects new or growing artifacts, it adds a failing check to the PR, preventing it from being merged.
- The developer reviews the changes in Gravity. If the changes are intentional and appropriate, they approve them. Otherwise, they address the issues.
- Once all changes are approved, the Gravity check turns green, and the PR is ready to merge.
Here's a brief video of Gravity in action:
Gravity consists of a set of core components:
- the CLI tool
@gravityci/cli
, which runs in your CI environment - The Gravity server, which processes uploaded artifacts, calculates differences, and hosts the UI for developers to review and approve changes.
- the GitHub app[1], which enables Gravity to interact with the repository, such as adding checks to pull requests.
The execution flow is roughly as follows:
anchor1. Artifact Upload
Each time CI runs, Gravity's CLI uploads the artifacts to S3. You can upload entire folders or individual files:
npx @gravityci/cli dist/ a-specifix-file.bin
Typically, you should use artifacts from a production build with all optimizations applied, ensuring Gravity analyzes the same files that ultimately reach your users.
anchor2. Artifact Analysis
Once the artifacts are uploaded, Gravity's CLI triggers their analysis. The Gravity server retrieves the artifacts from S3, analyzes them, and stores the results. If the CI run was not initiated by a pull request, the process concludes here—Gravity has analyzed the artifacts and stored the results for future use. This scenario typically applies to CI runs for a project's default branch, such as main
. If the CI run was triggered by a PR, the process continues as described in the next step.
anchorRust and NAPI-RS
To ensure efficient and reliable analysis of uploaded artifacts at scale, we implemented the analyzer in Rust and integrated it into the JS codebase using NAPI-RS. Initially, this part of the system was also implemented in JavaScript, but we encountered stability and resource issues. Switching to Rust significantly improved performance and reliability.
anchor3. Analysis Comparison
If the uploaded artifacts belong to a GitHub pull request, the Gravity server compares the analysis results with those of the PR's target commit. If there are no new artifacts and none have increased in size (i.e., no changes or only artifacts that have shrunk), Gravity adds a successful GitHub status check to the pull request, automatically approving the changes:

To interact with GitHub API, we use Octokit (where I'm a regular contributor 🙌).
If new artifacts are detected or existing ones have grown in size, a failing status check is added:

These changes require manual review and approval by the developer to ensure they are intentional and appropriate.
anchor4. Review and Approval
Developers can review artifact size changes in Gravity's dashboard, a Remix app that displays which files have changed and by how much.
If the developer approves the difference, Gravity updates the status check in GitHub, allowing the pull request to proceed to merge:

anchorFuture Plans
Currently, Gravity supports public GitHub repositories only. We plan to expand support to additional code hosting platforms and CI environments in the future. Also, the system would allow for more advanced analyses beyond just file sizes, such as:
- inspecting uploaded artifacts for deeper insights
- adding charts to track artifact sizes over time
- displaying the actual diffs that cause size changes
We'd love to hear your ideas for Gravity—feel free to share your thoughts!
Currently, Gravity supports GitHub and GitHub Actions only but we plan to add support for more code hosting platforms and CI environments in the future. ↩︎