client_java: the Prometheus instrumentation library with a 1,200-character README
Prometheus instrumentation library for JVM applications
At a glance
- What is it?
- Twenty-four published modules, a JDK 8 badge, and documentation that lives entirely on an external site. What the repository does not tell you is the interesting part.
- Who is it for?
- client_java is the right choice for a Java or JVM service that needs to expose Prometheus metrics and is on the 1.x line, and the module split means you depend on an exporter module rather than the whole library. Two checks decide whether it fits.
- 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?
- Yes. The repository last received commits 14 days 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
A README that is a pointer, not a guide
The README for prometheus/client_java runs to 1,243 characters. It contains two badges, a link to the documentation site, a contributing pointer, a Slack channel name, a fortnightly community call, a note about where old source lives, and the licence line. There is no dependency snippet, no Gradle or Maven coordinate, no code example, no configuration section, and no list of what the library does.
https://prometheus.github.io/client_javaEverything a user needs is one click away on the hosted documentation site, and that division is deliberate rather than lazy. The library sits in the middle of a chain of at least three projects: the Prometheus server that scrapes, this library that exposes and instruments, and the OpenTelemetry ecosystem that the exporter modules bridge into. A README that tried to summarise all of it would go stale against three upstream projects at once, so the project pushes that work to the site instead.
The cost is real for anyone evaluating without a browser. If your question is which module to depend on, or whether a particular instrumentation is in this repository or somewhere else, the README gives you nothing to go on and you have to read the module list yourself. The repository is Apache 2.0 licensed, has 2290 stars and 832 forks, and its last push was on 2026-09-28, which is recent enough that the module list in the tree reflects the current line rather than a historical one.
Twenty-four modules, and the split is the design
The tree is the real documentation. There are 24 directories whose names begin with prometheus-metrics, which tells you immediately that this is a BOM-driven multi-module Maven project rather than a single library. The modules group into a few families.
The core is split four ways. prometheus-metrics-model holds the data model, prometheus-metrics-core holds the registry and collectors, prometheus-metrics-config holds configuration, and prometheus-metrics-parent is the parent POM. On top of that, prometheus-metrics-bom is the bill of materials, and prometheus-metrics-instrumentation-jvm is the one module most Java users end up depending on directly because it provides the JVM metrics.
Exporters are where the count multiplies. There is a separate module per sink.
prometheus-metrics-exporter-httpserver/
prometheus-metrics-exporter-servlet-jakarta/
prometheus-metrics-exporter-servlet-javax/That pair is worth pausing on. The Jakarta and Javax servlet exporters are separate artifacts because the servlet namespace changed in Jakarta EE 9 and there is no single artifact that serves both worlds. That is a compatibility decision the module layout records for you, and it is the kind of thing you only discover when your build fails to resolve.
There are three shaded modules, exporter-opentelemetry-shaded, exposition-formats-shaded, and a bridge to the old client, prometheus-metrics-simpleclient-bridge. The shaded ones exist to hide their dependencies from consumers who would otherwise get version conflicts from transitively pulling in OpenTelemetry or an exposition format library. The simpleclient bridge is the migration path for 1.x code that still calls into the 0.x API.
The 1.x line replaced simpleclient, and the bridge is how you cross over
The README's only substantive technical statement is its last section, which says the source code for 0.16.0 and older is on the simpleclient branch. That branch name is the important part, because the 0.x library was called simpleclient and the entire 1.x line is a rewrite rather than an increment.
The practical consequence is that there are two incompatible APIs and they are not the same library at different versions. If you are porting existing code, the module to reach for is the bridge.
prometheus-metrics-simpleclient-bridge/A bridge module in this position usually does one of two things, and the difference matters for your migration. Either it exposes the old collector interface on top of the new registry so that old collectors keep working inside a 1.x application, or it exposes new-style metrics through the old registry API so that an unchanged 1.x application can keep scraping old-style output. Which direction this one works in is not stated in the README, and it is the first thing to check on the documentation site before you plan a migration around it.
Note also that the repository keeps a directory called simpleclient-archive alongside the bridge, and that the old source lives on a branch rather than in that directory. Both are true, and they answer different questions: the archive directory is part of the current build, while the branch is the historical 0.x line. If you are looking for 0.16.0 source, the branch is the right place and the archive directory is not.
1.9.0 is a release about bounding what a caller can make you do
The three most recent releases tell you what the project currently spends its attention on, and they are not feature work. Version 1.7.0 shipped on 2026-06-03, 1.8.0 on 2026-06-11, and 1.9.0 on 2026-09-16, which is an unusually tight gap for a library of this age followed by a quiet quarter.
Version 1.9.0 lists one feature and four fixes, and three of those fixes are about limits. It bounds HTTPServer request resources, bounds observation buffering during collection, and bounds scrape query parameters. Read together, they address a specific failure mode: a library that exposes an HTTP endpoint will be scraped by anything that can reach it, and an unbounded exporter is a denial-of-service surface aimed at your own service. Bounding the query parameters a scrape may carry is the fix for a request that arrives with a pathological filter expression.
The fourth fix is different in kind and easier to recognise as a class of bug. It avoids protobuf debug reflection in native images, which matters if you compile to GraalVM native, where reflection over protobuf internals tends to fail at build time or at first call.
The one feature is narrower than it sounds. Support for metric name filtering in the OpenTelemetry exporter lets you restrict which metrics cross the bridge, which is how you keep an OpenTelemetry backend from being flooded by every JVM internal.
Two of the four fixes were released within eight days of 1.7.0 in the 1.8.0 line, which included a dependency bump of Spring Boot to 4.1.0. That version number is worth noting on its own, since a metrics library tracking Spring Boot majors this closely is signalling that its own servlet and Spring integrations move with the platform.
API stability is now machine-checked, and the diffs are in the repository
Version 1.7.0 introduced three changes that together amount to a compatibility policy. It added a stable API marker and an API diff check, it added typed metric family descriptors, and it started tracking the API diff baseline through Renovate while storing the diffs under docs/apidiffs.
That third item is the one to act on. Storing diffs means the repository itself is the record of what changed between versions, which is unusual and useful: you can read what moved without installing anything or trusting a changelog summary. If you are evaluating an upgrade, that directory is a concrete first step rather than a guess.
The typed family descriptors are the more structural change. The 1.8.0 release notes then add documentation covering typed family descriptors and the stable API marker as available since 1.6.1, which puts a specific floor under the feature. So the marker landed in 1.7.0 and the capability it marks goes back to 1.6.1. Both statements come from the release notes and they are consistent once you read them as the marker being introduced later than the API it marks.
Version 1.8.0 also deprecates the wide constructors on MetricMetadata.Builder in favour of a Builder, and adds custom labels to exemplars. Deprecating wide constructors is a normal way to buy optional parameters without breaking source compatibility, but it does mean your build will start warning, and a project with warnings treated as errors will need the migration before it can adopt 1.8.0.
The JDK 8 badge and the modern build, side by side
The README carries a badge that reads JDK compatibility 8 and up. The repository around it is built with a wrapper, a mise toolchain with a lock file, and a checkstyle configuration, and the tree contains both AGENTS.md and CLAUDE.md, which are the current-generation instructions files that coding agents read. A project that ships agent instruction files at the repository root is one whose contributors are expected to hand large changes to automated tooling.
Those two facts are not contradictory, but they are in tension in a way you should resolve before committing. The badge describes a promise about the bytecode level of the published artifacts. The build system describes what the maintainers use. A library can absolutely keep Java 8 compatibility while adopting a modern toolchain internally, and plenty do, but the badge is a claim the repository does not substantiate anywhere a reader can check without building.
The version-rules.xml file at the root is the piece that would settle it. Version rules in a Maven build are how you pin or force dependency versions, and a project that ships one is managing a compatibility surface deliberately. Nothing in the README points at it.
So the check is: read version-rules.xml and the parent POM, and confirm the source and target levels for the modules you intend to depend on. The instrumentation-jvm module in particular is the one most applications take, and it is a separate artifact from the exporters, so it is entirely possible for it to sit at a different floor from the HTTP exporter. Do not take the badge as covering all 24 modules without looking.
Eleven example projects, and where to start reading
The examples directory is where the library actually teaches, and it is more informative than the README by an order of magnitude. There are eleven runnable example projects, and reading their directory names tells you what the project considers the interesting problems. A sibling directory called benchmarks sits alongside them, so the project treats measurement questions as a first-class concern rather than an afterthought.
Three of the examples are specifically about measurement choices that people get wrong. example-custom-buckets exists because histogram bucket boundaries are the single most consequential configuration choice in a metrics library and the default is rarely right. example-native-histogram does the same for native histograms, where the bucket configuration moves into the instrumentation rather than the exporter. And example-exemplars-tail-sampling exists because exemplars are how you link a metric spike to a trace, but only if the tail is sampled the way your exemplar distribution assumes.
Two target migration and configuration. example-simpleclient-bridge pairs with the bridge module discussed earlier, and example-prometheus-properties shows the properties-based configuration route as an alternative to the programmatic one.
Four cover delivery paths. example-exporter-httpserver, example-exporter-multi-target, example-exporter-opentelemetry and example-exporter-servlet-tomcat each isolate one exporter, and the Tomcat one is the case where you may need to resolve the Jakarta or Javax split.
The last is example-otel-jvm-runtime-metrics, which covers collecting JVM runtime metrics through the OpenTelemetry path rather than the plain Prometheus one. If you are adopting this library, example-custom-buckets is the one worth reading first, because a histogram with default buckets gives you a metric that looks like it works and cannot answer the question you are asking it.
Editorial conclusion
client_java is the right choice for a Java or JVM service that needs to expose Prometheus metrics and is on the 1.x line, and the module split means you depend on an exporter module rather than the whole library. Two checks decide whether it fits. Confirm your JDK target, because the compatibility badge reads 8 plus while the build system and the module set are considerably newer, and the repository does not publish a per-module compatibility floor you can read without visiting the documentation site. Then confirm the API surface you depend on is annotated as stable, since 1.7.0 added a machine-checked stability marker and the release notes point to stored API diffs under docs/apidiffs as the way to see what moved. Skip this library if you are still on the 0.x line, because the source for 0.16.0 and earlier lives on a separate branch and the two lines do not share an API.
Frequently asked questions
What does client_java do for Prometheus metrics in a JVM application?
It is the Prometheus instrumentation library for JVM applications. It provides a registry and collectors, a module that exports JVM runtime metrics, and one exporter module per delivery path including an HTTP server, Jakarta and Javax servlets, a push gateway, and OpenTelemetry.
What is the difference between the simpleclient branch and client_java 1.x?
Version 0.16.0 and older live on a separate branch called simpleclient, and the 1.x line is a rewrite with an incompatible API. The current tree keeps a prometheus-metrics-simpleclient-bridge module, which is the migration path for code still calling the 0.x API.
Which client_java release should I use for JVM instrumentation?
The most recent is 1.9.0, published on 2026-09-16, after 1.8.0 in June and 1.7.0 earlier in June. Version 1.9.0 is mostly a hardening release that bounds HTTP request resources, observation buffering and scrape query parameters, plus a fix for protobuf reflection in native images.
How do I check whether a client_java API is stable before upgrading?
Version 1.7.0 added a stable API marker together with an API diff check, and the release notes say the diffs are tracked through Renovate and stored under docs/apidiffs in the repository. Reading that directory shows what changed between versions without building anything.
Does client_java work on JDK 8?
The README carries a badge that reads JDK compatibility 8 and up. The repository does not publish a per-module compatibility floor in the README, so if you need certainty for a specific module, read version-rules.xml and the parent POM in the repository root.
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/prometheus-client-java)