> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devin.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Differential builds

> Speed up snapshot builds by only rebuilding workspaces whose blueprints changed. Unchanged workspaces are inherited from the previous successful build.

## Overview

By default, every snapshot build is a **full build** — it starts from a clean base image, clones all repositories, and runs every blueprint from scratch. This ensures a completely reproducible environment, but can be slow when you only changed one blueprint out of many.

**Differential builds** optimize this by reusing the previous successful build's snapshot as a starting point. Only workspaces whose blueprints actually changed are rebuilt; unchanged workspaces are inherited as-is from the parent build. This can significantly reduce build times, especially for organizations with many repositories.

## Enabling differential builds

<Steps>
  <Step title="Navigate to environment settings">
    Go to **Settings > Environment > Advanced**.
  </Step>

  <Step title="Enable the toggle">
    Turn on the **Differential builds** toggle. The description reads: *"Faster builds by reusing unchanged workspaces."*
  </Step>

  <Step title="Trigger a build">
    Save a blueprint change or click **Build snapshot**. The next build will attempt to run as a differential build if a valid parent build exists.
  </Step>
</Steps>

<Warning>
  The first build after enabling differential builds will always be a **full build** — the system needs a successful baseline snapshot to compare against. Subsequent builds will be differential as long as a valid parent exists.
</Warning>

## How it works

When a build is triggered with differential builds enabled, the system follows this process:

### 1. Find a parent build

The system looks for the most recent successful build (status `success` or `partial`) to use as a parent. If no qualifying parent exists, the build falls back to a full build automatically.

### 2. Compare blueprints

Each workspace's configuration is compared against the parent build. The system computes a digest of each workspace's inputs — including blueprint contents, attached files, secrets, and repository order — and checks what changed.

### 3. Assign workspace actions

Based on the comparison, each workspace gets one of three actions:

| Action      | What happens                                                                       | When it's used                                    |
| ----------- | ---------------------------------------------------------------------------------- | ------------------------------------------------- |
| **Rebuild** | Clone the repo and run all blueprint steps (initialize + maintenance) from scratch | Blueprint changed since the parent build          |
| **Inherit** | Pull the latest code and run only `maintenance` steps                              | Blueprint is unchanged — reuse the parent's setup |
| **Remove**  | Delete the workspace from the snapshot                                             | Workspace was removed from the configuration      |

<Info>
  For inherited workspaces, `initialize` does not run again. Write `maintenance`
  so it is self-contained and can run independently after the latest code is
  pulled. It can use tools and runtimes already installed in the parent snapshot,
  but it must not require `initialize` to run immediately beforehand or rely on
  environment variables that `initialize` previously wrote to `$ENVRC`.
</Info>

### 4. Execute the build

The build starts from the parent build's snapshot image instead of a clean base. This means:

* **Inherited workspaces** already have their tools, runtimes, and dependencies installed. The system pulls the latest code (`git pull`) and runs `maintenance` commands to update dependencies.
* **Rebuilt workspaces** are set up from scratch — cloned fresh and run through the full `initialize` + `maintenance` sequence.
* **Removed workspaces** have their directories cleaned up.

Organization and enterprise blueprints skip `initialize` during differential builds (since those tools are already present in the parent image) and run only `maintenance`.

<Note>
  `$ENVRC` is reset at the start of every build, including differential builds.
  Environment variables and `PATH` entries written to `$ENVRC` by a previous
  build are not inherited. If `maintenance` needs them, it must configure them
  itself.
</Note>

## When a full build runs instead

Even with differential builds enabled, the system falls back to a full build in certain situations:

* **No parent build exists** — first build, or all previous builds failed
* **Organization or enterprise blueprint changed** — global changes affect all workspaces, so a clean rebuild is safer
* **Repository ordering changed** — since repos can depend on each other's setup, reordering triggers a full rebuild
* **Parent build is too old or incompatible** — the system validates that the parent is suitable

When a fallback happens, the build detail page shows the reason under the build kind badge.

## Viewing build kind

After a build completes, you can see whether it ran as a differential or full build:

1. Go to **Settings > Environment > Snapshots**
2. Click on a build in the history
3. The **Build kind** badge shows either **Differential** (blue) or **Full build** (default)

Hover over the badge for a tooltip explaining what each kind means:

* **Differential**: *"Only changed workspaces are rebuilt; unchanged ones are inherited from the last successful build with the same configuration"*
* **Full build**: *"All workspaces are built from scratch"*

## Benefits

| Benefit                | Description                                                                                                                           |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Faster builds**      | Only changed workspaces go through the full setup process. Inherited workspaces skip `initialize` entirely.                           |
| **Less network usage** | Unchanged workspaces don't re-download tools, runtimes, or large dependencies.                                                        |
| **Quicker iteration**  | When iterating on a single repo's blueprint, other repos don't slow down the build.                                                   |
| **Same reliability**   | If anything looks wrong, the system automatically falls back to a full build. You can also manually trigger a full build at any time. |

## Manually triggering a full build

Even with differential builds enabled, you can force a full build from the **Build snapshot** button. Use the dropdown to select **Full build** instead of the default differential option.

We recommend running a full build periodically to discard inherited state and verify that your blueprints can still create the environment from scratch. Also run one after removing or replacing setup that may have left stale files, tools, or dependencies in the snapshot. A full build reruns all `initialize` and `maintenance` steps.

## FAQ

<AccordionGroup>
  <Accordion title="Does enabling differential builds affect my sessions?">
    No. Sessions always boot from the final snapshot regardless of how it was built. The only difference is build speed.
  </Accordion>

  <Accordion title="What if a differential build produces a bad snapshot?">
    Pin a previous known-good build from **Settings > Environment > Snapshots**, then trigger a full build to get a clean snapshot. You can also disable differential builds entirely to go back to full builds.
  </Accordion>

  <Accordion title="Do partial builds qualify as parents?">
    Yes. A build with status `partial` (some workspaces succeeded, some failed) can serve as a parent. The system inherits only from workspaces that succeeded in the parent.
  </Accordion>
</AccordionGroup>
