Infrastructure worth keeping — and kept patched.

Can I Restart the Cache Server While Builds Run?

Yes. In our runs, a build that was already running finished normally when we stopped and restarted FosterStack Cache. It printed at most one warning and stopped using the cache for the rest of that build.

The short answer

What to do

Our advice, not a test result:

If the server is down for a whole build, nothing breaks either. That case is on what happens when the cache server is down.

Does the build cache survive a restart?

You restart the cache server, or it crashes, or the container is replaced. Do your stored build results come back? We tested a clean stop, a forced kill and a wrong data folder.

The results live in the data folder, not in the running server. If that folder survives, your cache survives.

If your cache comes back empty, the server is looking at a different folder than before. Check that the data folder or volume is still the one you expect:

To copy the data somewhere safe, or to move it to another server, see upgrade, back up and restore.

How we checked

We ran the Gradle builds on this page twice on a Mac, once with Java 21 and once with Java 27, with the same results. A third run on Linux is in the last section.

Restarts during a build. FosterStack Cache 0.2.1 on a Mac (arm64), no password. Gradle 9.8.0, one fresh copy of the project per build, no reused daemon, the local build cache off. To keep builds open long enough to overlap a restart, each of the four modules had a cacheable task that sleeps for 8 seconds. We sent the signal to the server's process ID and started it again on the same data folder. All builds ended with BUILD SUCCESSFUL. Each row is one run; we did not repeat them.

Server stopped during the buildBack afterWhat the build printedEntries storedNext build, from cache
Normal stop2 secondsNothing about the cache4 of 44 of 4
Kill2 secondsNothing about the cache4 of 44 of 4
Normal stop14 secondsOne Could not store entry, then the remote cache was disabled2 of 42 of 4
Kill14 secondsOne Could not store entry, then the remote cache was disabled2 of 42 of 4

We also started a build while the server was stopped. It printed one Could not load entry warning, then built all four modules locally. After we started the server, the next build built and stored all four. The one after that took all four from the cache.

How long the server was unreachable. We stopped and started it five times in a row for each case, and polled /healthz until it answered. This measures the restart on a busy laptop, not a promise for your server.

Data in the cacheNormal stop, then startKill, then start
20 small entries0.03 to 0.05 seconds0.03 seconds
5,000 entries, about 49 MiB0.03 to 0.06 seconds0.05 to 0.15 seconds

After a kill, the server logs unclean shutdown detected, reconciling stores before serving and checks its files before it answers. No entries were lost in these runs.

An upload in progress when the server stops. To catch an upload in progress we used curl to send a large file slowly (2 MiB per second) and stopped the server 3 seconds in.

UploadStopWhat happenedEntry afterwards
20 MiBNormal stopThe server waited, the upload finished with 201, the server exited cleanly after 7.4 secondsReadable
20 MiBKillThe upload broke. A 6 MiB temporary file stayed behindNot found (404). The next start removed the temporary file
40 MiBNormal stopThe server gave up after 10.0 seconds and exited with an error. The upload broke. A 26 MiB temporary file stayed on diskNot found (404)

In both 20 MiB cases, an entry that was stored earlier stayed readable. We did not test whether a later start removes the temporary file left by the 40 MiB case.

What survives a restart. A four-module Gradle 9.8.0 project (the one from Gradle build cache for a monorepo) against a server set up with FSCACHE_DATA_DIR pointing at a folder, on FosterStack Cache 0.2.1 (macOS, arm64). Every build used a fresh copy of the project and an empty Gradle home, so the only shared thing was the server. Our first run used a project folder that still held build output from an earlier check; we repeated all four steps from a clean copy and got the same results. All four builds ended with BUILD SUCCESSFUL. "From cache" counts the four compileJava tasks that printed FROM-CACHE.

StepServer state before the buildEntries in the status pageFrom cache
1. First buildNew, empty data folder A0, then 13 afterwards0 of 4
2. Clean restartStopped normally, started on folder A13 (same as before)4 of 4
3. CrashKilled with kill -9, started on folder A13 (same as before)4 of 4
4. Wrong folderStarted on a different empty folder B00 of 4

The status page is the server's /statusz address. It showed the same 13 entries and the same size in bytes right after each restart, before any build ran.

In this test we killed the server while it was idle. Kills in the middle of an upload are in the upload table above.

Not tested: Docker, Kubernetes or Compose rollouts, Maven builds, releases other than 0.2.1 and 0.2.2, and more than one build running at once.

Second run: Linux, 0.2.2

The runs above were on a Mac with 0.2.1. We ran the same steps again on a GitHub-hosted Linux machine with FosterStack Cache 0.2.2, Gradle 9.8.0 and Java 21. In the build tests we stopped the server while the build's third 8-second task was running, 2 seconds after the second one finished.

The run and its log are public.