My experience with Bazel at a startup (also used Blaze at Google):
The good:
- Amazing for Go backends. I can push a reproducible Docker image to Kubernetes with a single Bazel command. I can run our entire backend with a single command that will work on any developer's box.
- Amazing for testing. All of our backends tests use a fully independent Postgres database managed by Bazel. It's really nice not having to worry about shared state in databases across tests.
- We can skip Docker on macOS for development which provides on the order of a 10x speedup for tests.
- BuildBuddy provides a really nice CI experience with remote execution. Bazel tests are structured so I can see exactly which tests failed without trawling through thousands of lines of log output. I've heard good things about EngFlow but BuildBuddy was free to start.
- Really nice for schema driven codegen like protobufs.
The bad:
- Bazel is much too hard for TypeScript and JavaScript. We don't use Bazel for our frontend. New bundlers like Vite are much faster and have a developer experience that's hard to replicate with Bazel. Aspect.dev is doing some work on this front. One large hurdle is there's not automatic BUILD file dependency updater like Gazelle for Go.
- Windows support is too hard largely because most third party dependencies don't work well with Windows.
- Third party dependencies are still painful. There's ongoing work with bzlmod but my impression is that it won't be usable for a couple of years.
- Getting started was incredibly painful. However, the ongoing maintenance burden is a few hours per month.
> Bazel is much too hard for TypeScript and JavaScript. We don't use Bazel for our frontend. New bundlers like Vite are much faster and have a developer experience that's hard to replicate with Bazel. Aspect.dev is doing some work on this front. One large hurdle is there's not automatic BUILD file dependency updater like Gazelle for Go.
I built this[0] for the Bazel + yarn setup that we use at Uber. We currently manage a 1000+ package monorepo with it.
> I can run our entire backend with a single command that will work on any developer's box.
Curious wouldn't `go run` give you the same? pure go code is supposed to be portable, unless you have cgo deps I guess?
> I can push a reproducible Docker image to Kubernetes with a single Bazel command.
That's definitely an upside over what would otherwise would probably default to a combination of Dockerfiles and scripts/Makefiles, does it worth bringing in the massive thing that is Bazel? depends I guess.
I'm curious: would you say your experience with golang IDEs / gopls is degraded? did you do anything special to make it good? I often feel like development is more clunky and often I just give up on the nice-to-haves of a language server e.g often some dependencies in the IDE aren't properly indexed, I can probably get Bazel to do some fetching, reindex and get it working, but it will take 3-4 minutes and I just often choose to live with the thing appearing as "broken" in the IDE and getting less IDE features.
We use protobufs and pggen. Bazel transparently manages the codegen from proto file to Go code.
> would you say your experience with golang IDEs / gopls is degraded?
Yes, that's our biggest pain point with Go and Bazel. I haven't been able to coax IntelliJ into debugging Bazel managed binaries. To enable IntelliJ code analysis, we copy the generated code into the src directory (with a Bazel rule auto-generated by Gazelle) but don't add it to Git.
I've tried the IntelliJ with Bazel plugin a few times but I've always reverted back to stock IntelliJ.
> Amazing for testing. All of our backends tests use a fully independent Postgres database managed by Bazel. It's really nice not having to worry about shared state in databases across tests.
I would love to know more about this. We use bazel and Postgres, but there is no Postgres isolation between tests currently which is very predictably a large source of flakyness, and also a blocker for increasing test parallelism.
I’ve been scheming on perhaps using pg_tmp orchestrated outside of bazel, but if there’s a way to do everything in bazel that would make the transition way easier.
Not OP, but we start small postgres instances in our Python tests with some py.test fixtures. The actual postgres binaries are provided by Bazel, so nothing relies on outside installations.
That said, this requires one postgres instance for each test, which is pretty heavy. So we keep our tests pretty coarse at the Bazel level (i.e. one Bazel test is actually 10+ Python tests). I've thought about other approaches, such as using a Bazel persistent worker to wrap test execution and manage a single Postgres instance with empty databases created from templates, but never got around to trying anything.
In addition to the techniques in the linked comment, I'm currently investigating managing the entire Postgres data dir as a Bazel output directory. That way, we avoid executing the schema for every test. Instead, we'd start a new Postgres cluster against the existing data dir without re-executing the schema or creating from a template DB.
The good:
- Amazing for Go backends. I can push a reproducible Docker image to Kubernetes with a single Bazel command. I can run our entire backend with a single command that will work on any developer's box.
- Amazing for testing. All of our backends tests use a fully independent Postgres database managed by Bazel. It's really nice not having to worry about shared state in databases across tests.
- We can skip Docker on macOS for development which provides on the order of a 10x speedup for tests.
- BuildBuddy provides a really nice CI experience with remote execution. Bazel tests are structured so I can see exactly which tests failed without trawling through thousands of lines of log output. I've heard good things about EngFlow but BuildBuddy was free to start.
- Really nice for schema driven codegen like protobufs.
The bad:
- Bazel is much too hard for TypeScript and JavaScript. We don't use Bazel for our frontend. New bundlers like Vite are much faster and have a developer experience that's hard to replicate with Bazel. Aspect.dev is doing some work on this front. One large hurdle is there's not automatic BUILD file dependency updater like Gazelle for Go.
- Windows support is too hard largely because most third party dependencies don't work well with Windows.
- Third party dependencies are still painful. There's ongoing work with bzlmod but my impression is that it won't be usable for a couple of years.
- Getting started was incredibly painful. However, the ongoing maintenance burden is a few hours per month.