Can Two Jobs Share One Docker Builder?

Yes. Jobs that name the same builder profile land on one builder VM, share its layer cache, and bill as one session. Concurrency, sizing, and cost.

Yes. Two GitHub Actions jobs that pass the same profile-name to the WarpBuild build action land on the same remote builder VM, share that VM's persistent layer cache, and bill as a single session. The Docker builders documentation states that each builder profile corresponds to one dedicated builder virtual machine with caching, and that multiple jobs using the same builder profile run on that VM in parallel.

Answer

The builder profile is the unit of sharing. Two jobs share a builder when they name the same profile, whatever runner label they carry and whatever workflow file they live in.

Three things are shared the moment two jobs name the same profile:

  • The VM. One profile maps to one dedicated builder virtual machine. Two jobs pointing at it run their builds on that machine at the same time.
  • The layer cache. The cache lives on the builder's local disk, so the second job's build reads layers the first job's build wrote. This is why cache-from and cache-to are unnecessary with a builder profile, per the Docker builders documentation, and why the runner's own cache is a separate mechanism with a separate lifetime.
  • The session. Builders bill per session. Jobs with overlapping execution on one profile share one session, measured from the first job's builder start to the last job's completion.

The concurrency behavior has two documented halves. There is no limit on the number of builds that can run concurrently on a builder profile, and the recommended minimum resource requirement is approximately 8 vCPU and 16GB memory per build job. So the profile will accept the fifth concurrent build; the size you picked decides whether that build gets the resources the Docker builders documentation recommends.

Cache consistency between two builds running at the same instant is the part teams get wrong. The Docker builders documentation describes the cache on a profile as shared but eventually consistent: a layer produced by one concurrent build may not be visible to another concurrent build, and it becomes available to later builds after synchronization. Two jobs that start together and build the same base image will each build those base layers once. The same two jobs staggered by a few minutes, or run again tomorrow, read them from the profile.

Run as many jobs as your workflows need. Generally available Linux and Windows runners do not have plan-level concurrency caps. The builder is sized independently of the runner: the Docker builders documentation is explicit that the size of the Docker machine is not related to the size of the GitHub runner the job uses. Both resources are billed, so a job that runs on a WarpBuild runner and builds on a WarpBuild builder pays runner minutes and builder minutes.

Detail

Two jobs on one profile, a third on its own

The profile is named per build step, so a workflow can mix them. Here api and worker share acme-services, and docs-site uses a separate profile with a separate cache and a separate session.

name: images

on:
  push:
    branches: [main]

jobs:
  api:
    runs-on: warp-ubuntu-latest-x64-4x
    steps:
      - uses: actions/checkout@v5

      - name: Build and push api
        uses: Warpbuilds/build-push-action@v6
        with:
          context: ./services/api
          push: true
          tags: acme/api:${{ github.sha }}
          profile-name: "acme-services"

  worker:
    runs-on: warp-ubuntu-latest-x64-4x
    steps:
      - uses: actions/checkout@v5

      - name: Build and push worker
        uses: Warpbuilds/build-push-action@v6
        with:
          context: ./services/worker
          push: true
          tags: acme/worker:${{ github.sha }}
          profile-name: "acme-services"

  docs-site:
    runs-on: warp-ubuntu-latest-x64-4x
    steps:
      - uses: actions/checkout@v5

      - name: Build and push docs site
        uses: Warpbuilds/build-push-action@v6
        with:
          context: ./sites/docs
          push: true
          tags: acme/docs:${{ github.sha }}
          profile-name: "acme-docs"

The api and worker images share a Debian base and a set of shared Go modules, which is the reason to put them on one profile: the first build to pull that base populates the disk for the other. The docs site shares nothing with either, so it gets its own profile and stops competing for the same builder disk.

No api-key input appears in this workflow because all three jobs run on WarpBuild runners, where the key is not required. Jobs on GitHub-hosted runners or any other runner need api-key: ${{ secrets.WARPBUILD_API_KEY }} added to each step, which is how the same profile can be shared by jobs that run nowhere near each other.

How the shared session is billed

The Docker builders documentation gives the timeline explicitly. Two jobs, J1 and J2, use the same x64 profile: J1's builder starts at t1 and the job completes at t2, J2's builder starts at t3 and the job completes at t4, with t1 < t3 < t2 < t4. That is billed as one session from t1 to t4.

Put minutes on it. Say J1 runs from minute 0 to minute 9 and J2 from minute 4 to minute 13, both on the 32 vCPU, 64GB, 200GB profile at $0.12 per minute from the Docker builders documentation, checked on 2026-08-13.

SetupSessionsBilled builder minutesCost
One shared profile1, from minute 0 to minute 1313$1.56
Two profiles of the same size2, of 9 minutes each18$2.16

Sharing costs $0.60 less on this run and gives both builds one warm cache instead of two cold ones. The shape generalizes: two overlapping builds on one profile bill the union of their spans, and two builds on separate profiles bill the sum. The union is always smaller when the builds overlap.

Sizing the profile you share

Divide the profile's vCPU by the documented 8 vCPU per concurrent build to get the number of builds it serves at the recommendation. Rates below come from the Docker builders documentation, checked on 2026-08-13.

Builder sizePrice per minuteConcurrent builds at 8 vCPU and 16GB eachArchitectures
16 vCPU, 32GB, 100GB disk$0.062amd64, arm64, multi
32 vCPU, 64GB, 200GB disk$0.124amd64, arm64, multi
64 vCPU, 128GB, 200GB disk$0.248amd64, arm64, multi
96 vCPU, 192GB, 600GB disk$0.3612amd64 only
96 vCPU, 192GB, 2TB disk$0.5212amd64 only
192 vCPU, 384GB, 600GB disk$0.7224amd64 only
192 vCPU, 384GB, 2TB disk$0.8824amd64 only

A three job matrix that builds all three images at once sits inside the 32 vCPU profile. A ten job matrix wants the 64 vCPU size. arm64 and multi-architecture profiles top out at 64 vCPU, so a wide matrix that also builds arm64 has to split across profiles rather than buy a larger one.

When a second profile is worth its own session

The break-even is stated in builder minutes, and it is strict. Splitting one profile into two replaces a session of N minutes with two sessions of N' and S minutes at the same rate, so the split pays only when the shared session loses at least S minutes: N - N' >= S.

In the example above, the second session lasts 9 minutes, so the shared session would have to fall from 13 minutes to 4 minutes to break even. That is shorter than either build, so on billing alone the second profile does not pay.

Here is what 10 minutes of second session costs at each size, so you can compare it against the minutes contention is costing you on the shared one.

Builder sizePrice per minuteCost of a 10 minute second session
16 vCPU, 32GB$0.06$0.60
32 vCPU, 64GB$0.12$1.20
64 vCPU, 128GB$0.24$2.40
96 vCPU, 192GB, 600GB disk$0.36$3.60
96 vCPU, 192GB, 2TB disk$0.52$5.20
192 vCPU, 384GB, 600GB disk$0.72$7.20
192 vCPU, 384GB, 2TB disk$0.88$8.80

Three situations clear that bar without needing a stopwatch:

  1. Architecture. A multi-architecture build runs each architecture on a separate builder instance, so one multi-arch profile already opens two sessions that bill independently. Splitting amd64 and arm64 into their own profiles changes the cache layout, not the session count.
  2. Cache competition. Images that share no base layers still share the profile's disk, from 100GB on the smallest size to 2TB on the largest. Unrelated images evicting each other's layers is a cache problem that a bigger disk or a second profile both solve, and the second profile is usually cheaper.
  3. Blast radius. A profile can be reset through the cache reset endpoint, and its cache is dropped automatically after a 10 day TTL of no use. One profile per image family keeps a reset or an expiry from cooling every build in the organization at once.

Sizing up the shared profile is the other move, and it is worth pricing against the split. Going from 32 vCPU to 64 vCPU adds $0.12 per minute on one session; adding a second 32 vCPU profile adds $0.12 per minute for however long that second session runs. The larger single profile keeps one cache, which is the reason to prefer it when the images are related.

What happens when two builds hit the same builder profile at the same time?

They run in parallel on the same builder VM. There is no documented limit on the number of builds that can run concurrently on one profile, and the documented recommended minimum is approximately 8 vCPU and 16GB memory per concurrent build job, per the Docker builders documentation. The concurrent Docker builds guide works through matrix builds that exceed that recommendation.

Do concurrent builds see each other's cache layers?

The cache is shared but eventually consistent. A layer written by one build may not be available to another build running at the same moment, and it becomes available to later builds after synchronization. Sequential builds on the profile get the full reuse. The guide to sharing a Docker cache between jobs covers the ordering patterns that make this predictable.

How is one profile billed when two jobs share it?

Builders are billed per session, measured from the first job's builder start to the last job's completion when the jobs overlap. A multi-architecture profile opens one session per architecture and each is billed independently. The remote Docker builders page lists every size and rate, and Docker builds on GitHub Actions covers the full setup from workflow file to builder profile.

Start with $10 in free credits

Change the runner label in your workflow and keep the rest of your GitHub Actions setup. Runner time is billed per minute.