Speed up GitHub Codespaces startup with prebuilds
Learn how GitHub Codespaces prebuilds move expensive container setup ahead of time, cut startup from minutes to seconds, and what trade‑offs to watch.
10 Oct 2025, 20:11 UTC

Problem: slow dev‑environment boot
When a teammate opens a GitHub Codespace, the first few minutes are often spent downloading the base image, running apt‑get or npm install, and executing postCreate scripts. For repositories that bundle large toolchains (e.g., Java JDK, .NET SDK, or compiled C++ dependencies) this wait can exceed five minutes, breaking the flow of quick experimentation.
Thesis: prebuilds move the heavy lifting ahead of time
GitHub Codespaces prebuilds assemble the dev container image—including dependency installation and any onCreate/postCreate steps—on a schedule or trigger. The resulting snapshot is stored in the selected region, so a new codespace can start from that ready image instead of rebuilding from scratch. The effect is a startup time that drops from minutes to seconds for many workloads.
How prebuilds work
A prebuild is essentially a GitHub Actions workflow that runs the same steps you would see during a normal codespace creation, but it runs in advance and saves the resulting container image. When a user launches a codespace, the service checks whether a matching prebuild exists for the branch and region; if it does, the VM boots from that image and only applies git updates and user‑specific secrets at runtime.
Key points:
- Prebuilds are branch‑scoped and region‑scoped. You must enable them per branch (usually the default branch) and per GitHub region where your team works.
- Configuration lives in the repository’s
.devcontainer/devcontainer.json(the usual dev container definition) plus a prebuilds trigger set either in the repository Settings → Codespaces → Prebuilds UI or via a.github/codespaces/prebuilds.jsonfile. - The trigger can be
on_push,on_configuration_change, or aschedule(cron). Theon_configuration_changeoption is often the safest default because it avoids burning Actions minutes on every commit.
Worked example: enabling prebuilds for a Java backend
Suppose your repository myorg/service‑api uses a dev container that installs OpenJDK 17, Maven, and a handful of internal libraries. The current codespace creation takes about 4 minutes.
1. Verify the dev container works
Make sure .devcontainer/devcontainer.json builds successfully when you create a codespace manually. No changes are needed here for prebuilds.
2. Add a prebuilds configuration file
Create .github/codespaces/prebuilds.json with the following content (run this in the repo root; you need write permission on the repository):
{
"prebuilds": [
{
"branch": "main",
"region": "us-east",
"trigger": {
"schedule": "0 3 * * *"
}
}
]
}
This tells GitHub to run a prebuild every day at 03:00 UTC on the main in the us-east region.
3. Trigger the first prebuild manually (optional)
If you want to see the result sooner, you can trigger a workflow run:
gh workflow run prebuilds.yml -r main
You need repo scope for the gh CLI. The workflow runs under the repository’s default GitHub Actions permissions; it will consume Actions minutes proportional to the time it takes to build the dev container.
4. Create a codespace and verify the prebuild was used
Open the repository on GitHub, click the “Code” button, select “Codespaces”, and click “New codespace”. After the VM starts, open the terminal and examine the creation log:
cat /workspace/.codespaces/logs/creation.log
Look for a line similar to:
Using prebuilt image: ghcr.io/myorg/service-api/devcontainer:prebuild-2026-10-01T03-00-00Z
If you see that line, the codespace launched from the snapshot. Compare the total elapsed time shown in the UI (or run time around a simple command) with a codespace created after temporarily disabling prebuilds (via the same UI toggle). You should observe a reduction from several minutes to under a minute for this example.
Trade‑offs and limitations
While prebuilds cut startup latency, they introduce two practical considerations:
- Storage and Actions cost: Each prebuild stores a container image in the selected region’s Codespaces storage and consumes GitHub Actions minutes for the build. Very large images (e.g., >10 GB) or frequent triggers (e.g.,
on_pushon a busy repo) can become a noticeable line item on your bill. - Freshness: A prebuild is only as current as its last run. Dependency changes that occur after the prebuild will still be installed at codespace creation time (via
apt-get updateornpm ci), but any change to the base image or topostCreatescripts will not appear until the next prebuild runs.
To keep costs predictable, start with the on_configuration_change trigger or a nightly schedule, monitor the Actions usage and Codespaces storage sections of your organization’s billing page, and adjust the frequency based on observed savings.
Practical verification checklist
- Enable prebuilds on a test branch (e.g.,
prebuild-test) with a schedule trigger. - Wait for the workflow to finish (check the Actions tab).
- Create a codespace from that branch and region.
- Search the creation log for the “Using prebuilt image” string.
- Record the startup time; repeat with prebuilds disabled to compare.
- After a week, review the billing reports to ensure the extra Actions minutes and storage stay within your budget.
Closing: make prebuilds part of your baseline
For repositories where the dev container includes heavyweight setup steps, enabling prebuilds is a low‑effort way to shave minutes off every developer’s workflow. Begin with a conservative trigger, validate the startup improvement and cost impact, then roll the setting out to your default branch and the regions where your team works. The result is a more responsive codespace experience without altering the day‑to‑day development process.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.