A fresh foundation for Pages builds

Cloudflare Pages has been steadily evolving since its December 2020 launch, growing to handle millions of deployments. The build system behind those deployments, however, had been running on defaults from that original era. Today that changes with a new beta build system that modernizes the default toolchain and, just as importantly, reworks the underlying architecture to make future updates far less disruptive.

The headline change: default versions are being brought up to date across the board. Node.js moves from 12.18.0 to 18.16.0, Python 2.7.18 and 3.10.5 are both available by default, Ruby jumps from 2.7.1 to 3.2.2, and Yarn moves from 1.22.4 to 3.5.1. The build system also adds pnpm with a default version of 8.2.0. Full details are listed in the language support documentation.

Because these new defaults represent a breaking change for projects that haven't pinned their toolchain versions, the new build system is opt-in for existing projects. Preview environments make it safe to test the new system before rolling it out to production. New projects, once the beta graduates to general availability, will use the updated system automatically.

Reproducibility also gets a boost. In the new build system, npm ci and yarn --pure-lockfile are invoked ahead of the build command, ensuring dependencies are installed strictly according to lockfiles rather than potentially drifting package resolution.

From monolith to modular containers

The architecture behind the updated build system is a more significant change than the version bumps suggest. Previously, a single monolithic container running on Kubernetes handled every stage of the build: cloning the git repository, installing custom tool versions, installing project dependencies, executing the user's build command, streaming logs, and uploading assets. That design created a coupling between system tooling and user-space requirements, which is why updating default versions was such an arduous process.

The new architecture breaks these steps into three separate containers that execute sequentially using Kubernetes' init containers feature:

  1. Cloning the user's git repository.
  2. Installing custom versions of languages and tools, installing dependencies, and running the build command.
  3. Uploading all build assets.

A shared volume provides a persistent workspace across all three containers. This separation creates clear isolation between system stages (clone and upload) and user stages (running code the developer is responsible for), eliminating conflicts between system tooling and user configuration while adding a security boundary around user-controlled code.

The upload stage itself is being aligned with the same APIs Wrangler uses for Direct Upload projects. Consolidating on one method of uploading assets and creating deployments reduces the maintenance burden and sets up further optimization work.

Log streaming across container boundaries

One consequence of the architectural split was that log streaming, previously a trivial matter of attaching to the container's stdout, required rethinking. The solution is a separate, global log collector container running inside Kubernetes that aggregates logs from multiple builds and forwards them to the same Durable Object infrastructure used by the dashboard. Since one collector handles many builds, each log entry is annotated with its originating build; a Worker in front of the Durable Object reads that annotation and routes the log stream to the correct build's Durable Object instance.

Build caching on the horizon

Today every Pages build starts from a clean slate. The modular design lays the groundwork to change that with build caching. The plan is a best-effort storage mechanism that lets developers persist and restore files between builds, enabling caching of dependencies and, for frameworks that support it, build output itself. The result should be considerably faster builds for the small, incremental changes that characterize most deployment workflows.

Trying the new system

Developers can opt in now from their Pages project settings in the Cloudflare Dashboard. The Pages team is also hosting a Q&A session on Discord to discuss the announcement.