Brave: Zipkin-compatible tracing instrumentation for Java services
Java distributed tracing implementation compatible with Zipkin backend services.
At a glance
- What is it?
- Brave is a dependency-free Java tracing library that propagates B3 context and times production requests. It fits teams already running a Zipkin-compatible collector, and it expects you to bring your own instrumentation.
- Who is it for?
- Adopt Brave when you already run a Zipkin-compatible collector and want tracing that adds no third-party jars to your dependency tree; the brave-bom import in your dependencyManagement section is the first thing to set up. Skip it if you need a tracing agent that instruments bytecode without code changes, or if your runtime predates JRE 1.6.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Activity is slowing. The repository last received commits 6 months ago.
- What is it written in?
- Mainly Java, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The gap Brave fills for JVM services
A request enters a Java service, calls two others, and the only evidence left behind is a log line with a timestamp. Brave exists to close that gap. The README describes it as a distributed tracing instrumentation library that "intercepts production requests to gather timing data, correlate and propagate trace contexts." The trace data usually goes to a Zipkin server, though the README notes third-party plugins can send it to alternate services such as Amazon X-Ray.
The audience is narrower than the description suggests. Brave is not an end-user tool and not a collector. It is a library you embed, plus a set of instrumentation modules for Servlet, OkHttp, gRPC, Kafka clients and others. The README is explicit that most users will not write tracing code directly: they reuse instrumentation others have written, and it points readers at the instrumentation directory and Zipkin's own list before rolling their own. If you are choosing a tracing stack for a Java service that already speaks HTTP or gRPC, that is the decision Brave is competing for. If you are choosing a browser, you are in the wrong repository.
How the tracer, context and B3 headers fit together
The repository splits into a small dependency-free tracer library under brave/ and a large set of instrumentation modules. The tracer is the underlying API that instrumentation use to time operations and add tags describing them. It also parses X-B3-TraceId headers, which is how an inbound request carries the trace context that lets spans in different services join up.
Two properties shape the architecture. First, the tracer library works against JRE 6 and adds no third-party dependencies. Second, every integration declares its associated library in provided scope, so Brave does not drag in a version of Servlet, gRPC or Kafka that conflicts with yours. The README states the goal plainly: to neither impact your projects' choices, nor subject your project to dependency decisions made by others. The practical consequence is that tracing a Servlet 2.5 application requires at least JRE 1.6, because the floor is 1.6 even though Servlet 2.5 itself works on Java 1.5.
Context propagation is a separate concern from span creation, and Brave keeps it in its own modules. The context/ directory holds integrations with tools such as SLF4J, which is what you reach for when you want trace IDs in log files or need to change thread-local behaviour. That separation is deliberate: span timing is one job, moving the current trace through threads and log frameworks is another, and they have different compatibility constraints.
Installing Brave with the Maven BOM and tracing an OkHttp call
Brave publishes to the group ID io.zipkin.brave and uses one common release version across components. The README recommends aligning versions in one place by importing the BOM in your dependencyManagement section, which is shown below. After that import, you can leave the version off any supported instrumentation artifact, and indirect uses are aligned too.
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-bom</artifactId>
<version>${brave.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>With the BOM in place, adding an instrumentation module is a single dependency with no version element, as the README shows for OkHttp 3:
<dependency>
<groupId>io.zipkin.brave</groupId>
<artifactId>brave-instrumentation-okhttp3</artifactId>
</dependency>The README also gives an override path: use the property brave.version to change dependency versions coherently, most commonly to test a new feature or fix. It adds a warning worth repeating, because it is the failure mode people hit. If you override a version, double check that your version is valid, meaning equal to or later than what you are updating, to avoid class conflicts. That is the whole install story for a Maven project. There is no daemon, no agent, no configuration file to point at, and no port to open. The repository does not document a Gradle-specific setup in the README, so Gradle users are translating the same coordinates themselves.
For a first real use, the README points at the brave-webmvc-example project rather than walking through a full application. That example is the honest starting point: wire the Servlet filter and the HTTP client instrumentation, send spans to a Zipkin server, and confirm that a request produces a trace rather than a single orphan span.
Where Brave stops being the right tool
Brave will not instrument anything you have not wired up. There is no bytecode agent in this repository, so a service that calls a database driver, a message broker or an internal RPC framework with no Brave module stays invisible until someone writes that instrumentation. The README acknowledges this by directing readers to existing instrumentation before writing their own, which is good advice and also a statement about scope.
The JRE 6 floor cuts both ways. It lets Brave run on old JREs and older Android runtimes, and the README names the cost directly: you cannot trace Servlet 2.5 applications until you are on at least JRE 1.6. A team on a very old stack may find the library will not load at all.
API drift in the libraries Brave integrates with is a standing maintenance problem rather than a one-time setup cost. The README says some libraries update often, leading to api drift, and that Brave tests version ranges for gRPC and Kafka clients to reduce the impact. Testing against multiple library versions is a mitigation, not a guarantee. If you upgrade Kafka clients or gRPC ahead of what Brave has been tested against, you are on your own until a release catches up. The README does not document a rollback procedure for a bad upgrade, so plan to test version bumps in a staging environment before they reach production.
Brave against OpenTelemetry Java instrumentation
The obvious alternative is OpenTelemetry's Java instrumentation, and the difference is architectural rather than cosmetic. Brave is a library-first design: you add dependencies, and each integration is a module you opt into, with the traced library in provided scope so it never overrides your version choices. The README's stated benefit is that including even a basic reporting library such as zipkin-sender-urlconnection transitively brings no json, logging, protobuf or thrift dependency, and the entire dependency tree including basic reporting in json, thrift or protobuf is less than 512KiB of jars.
OpenTelemetry's Java agent takes the opposite approach: attach it to the JVM and it instruments supported libraries without source changes. That is a better fit when you cannot modify the services, when you have dozens of applications and no appetite for editing each pom, or when you want one vendor-neutral SDK across languages. The trade is that you accept an agent in your runtime and its own compatibility matrix.
Brave's model suits a codebase where you control the build and care about the dependency graph. If your team has already standardised on Zipkin and B3 headers, Brave speaks that protocol natively. If you are starting fresh and expect to add non-Java services, the agent approach avoids re-solving the same problem per language.
Maintenance, version alignment and the Apache-2.0 licence
The last push to the repository was on 2026-03-25, and the most recent release listed is 6.3.1 from 2026-03-24. The preceding releases are 6.3.0 from 2025-06-01 and 6.2.0 from 2025-04-28, so the cadence between those three is uneven rather than monthly. The repository is not archived. Snapshots are uploaded to Sonatype after commits to master, which means unreleased fixes are available but carry the usual snapshot caveat.
Upgrade cost is mostly a version-alignment exercise, and the BOM exists to make it one. Import brave-bom, keep the version in a single property, and the individual instrumentation artifacts follow. The README's caution about overriding a version applies here: a downgrade or a mixed set of Brave versions is how you get class conflicts. When you use several brave components, aligning them in one place is what lets you upgrade with less worry about conflicts.
Brave is licensed under Apache-2.0, which permits commercial use and modification under its terms; the repository also carries a NOTICE file, which is where attribution requirements for a project like this typically live. Licence questions are for your own legal review, and this article does not give legal advice. One practical note from the README: all artifacts publish under the group ID io.zipkin.brave with a common release version, so a dependency report showing mixed io.zipkin.brave versions is a signal that the BOM is not doing its job.
Editorial conclusion
Adopt Brave when you already run a Zipkin-compatible collector and want tracing that adds no third-party jars to your dependency tree; the brave-bom import in your dependencyManagement section is the first thing to set up. Skip it if you need a tracing agent that instruments bytecode without code changes, or if your runtime predates JRE 1.6. Before committing, confirm which instrumentation module matches your framework version, and check that the release you pin is at least as new as the one you are replacing.
Frequently asked questions
What does Brave mean in the openzipkin/brave project?
In this project, Brave is the name of a distributed tracing instrumentation library for Java, and it is unrelated to the web browser of the same name. The README describes it as intercepting production requests to gather timing data and propagate trace contexts, usually to a Zipkin server.
Is Brave still free to use?
The repository is licensed under Apache-2.0, which permits use and modification under that licence's terms. The README does not describe a paid tier or a commercial edition of the library.
How do I install the Brave tracing library in a Java project?
Add the io.zipkin.brave:brave-bom artifact to your dependencyManagement section with scope import, then declare the instrumentation artifact you need without a version. The README shows brave-instrumentation-okhttp3 as an example of a version-free dependency once the BOM is imported.
Does Brave work on older Java versions?
Yes, the tracer library is stated to work against JRE 6 and later, and there is a floor Java version of 1.6. The README notes this means you cannot trace Servlet 2.5 applications until you use at least JRE 1.6.
Do I have to write tracing code myself with Brave?
Usually not. The README says most users will not write tracing code directly and instead reuse instrumentation others have written, pointing readers at the instrumentation directory and Zipkin's list of tracers and instrumentation before rolling their own.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/openzipkin-brave)