Skip to main content
The Bazel system is implemented as a long-lived server process. This allows it to perform many optimizations not possible with a batch-oriented implementation, such as caching of BUILD files, dependency graphs, and other metadata from one build to the next. This improves the speed of incremental builds, and allows different commands, such as build and query to share the same cache of loaded packages, making queries very fast. Each server can handle at most one invocation at a time; further concurrent invocations will either block or fail-fast (see --block_for_lock). When you run bazel, you’re running the client. The client finds the server based on the output base, which by default is determined by the path of the base workspace directory and your userid, so if you build in multiple workspaces, you’ll have multiple output bases and thus multiple Bazel server processes. Multiple users on the same workstation can build concurrently in the same workspace because their output bases will differ (different userids). If the client cannot find a running server instance, it starts a new one. It does this by checking if the output base already exists, implying the blaze archive has already been unpacked. Otherwise if the output base doesn’t exist, the client unzips the archive’s files and sets their mtimes to a date 9 years in the future. Once installed, the client confirms that the mtimes of the unzipped files are equal to the far off date to ensure no installation tampering has occurred. The server process will stop after a period of inactivity (3 hours, by default, which can be modified using the startup option --max_idle_secs). For the most part, the fact that there is a server running is invisible to the user, but sometimes it helps to bear this in mind. For example, if you’re running scripts that perform a lot of automated builds in different directories, it’s important to ensure that you don’t accumulate a lot of idle servers; you can do this by explicitly shutting them down when you’re finished with them, or by specifying a short timeout period.

Managing memory pressure across multiple workspaces

Because each distinct workspace uses its own output base, working across multiple repositories starts a dedicated Bazel server for each workspace. Even when idle, each server process retains in-memory caches (such as the Skyframe dependency graph and package representations) to keep subsequent incremental builds fast. If your machine experiences memory pressure due to multiple idle servers, you can configure global protection in your user-level ~/.bazelrc:
  • Shut down automatically on low RAM: Add startup --shutdown_on_low_sys_mem to instruct servers idle for more than 5 minutes to exit when host RAM becomes critically low (supported on Linux and macOS).
  • Reduce idle timeout: Lower startup --max_idle_secs=1800 (e.g. 30 minutes instead of the 3-hour default) so unused servers terminate earlier.
  • Explicit shutdown: Run bazel shutdown in workspaces you are done with.
The name of a Bazel server process appears in the output of ps x or ps -e f as bazel(dirname), where dirname is the basename of the directory enclosing the root of your workspace directory. For example:
This makes it easier to find out which server process belongs to a given workspace. (Beware that with certain other options to ps, Bazel server processes may be named just java.) Bazel servers can be stopped using the shutdown command. When running bazel, the client first checks that the server is the appropriate version; if not, the server is stopped and a new one started. This ensures that the use of a long-running server process doesn’t interfere with proper versioning.