# sql_exporter: a database-agnostic exporter for Prometheus

> SQL Exporter runs queries against your databases and exposes the results in the Prometheus format. The interesting part is that the metric definition is configuration rather than code, so a new metric does not need a new build, and the exporter supports a multi target job mode where one process scrapes many databases on one schedule and caches their results.

**burningalchemist/sql_exporter** — Database-agnostic SQL Exporter for Prometheus

- Repository: https://github.com/burningalchemist/sql_exporter
- Website: https://burningalchemist.github.io/sql_exporter/
- Stars: 603 · Forks: 110
- Language: Go
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/burningalchemist-sql-exporter

## The idea

SQL Exporter is described as a flexible database-agnostic exporter that exposes metrics gathered from databases in the Prometheus format.

That is a category of tool that fills a specific gap. Prometheus has exporters for almost everything, and the database exporters that do exist are usually one per engine, each with its own configuration format, its own metric naming, and its own release cycle. The result is that a company with a relational database, a document store, and a warehouse has three exporters to configure, three sets of dashboards, and three sets of alerts.

sql_exporter is the opposite approach. The metric definitions are configuration, the query is configuration, and the connection is configuration, so one binary and one configuration format cover every engine that has a driver.

The project is a continuation rather than a new thing, and the acknowledgements say so. The credit goes to the person who created the original implementation, then to the person who contributed the Helm chart and the development and release environment around it, then to the sponsor of the development, and then to the contributors who have improved the project over the years. The original implementation is the ancestor of a well known exporter in the same space, so this repository is what happens when somebody takes an idea that works, and keeps going with it.

The project is MIT licensed, the last push was on 2026-10-22, and the release history shows an active cadence with a version in the last week and another a few days before it. There is also a separate chart package versioned independently, which is the Helm chart published to a chart repository, and the readme links both a container registry and a chart repository.

The documentation is published as a site with a general configuration page, a full configuration reference, and a specific page for installation, and the readme defers all the instructions there rather than repeating them. That is a sign of a project where the configuration surface is large enough that a summary in the readme would be misleading.

## The feature list, and which of them change the design

The feature list has thirteen entries, and most of them are one line each, which is typical of an exporter. A few of them describe decisions that shape the whole thing rather than options.

The first is database-agnostic with broad driver support, which is the premise. The second is scrape-synchronous collection with optional caching, and that is the one that decides how the exporter behaves under load.

Scrape-synchronous means the default is to run the query when Prometheus scrapes, and to return the result. That is the honest behaviour for a database metric: the number you get is the number now. But it also means every scrape is a query against a live system, and a slow query becomes a slow scrape.

The optional cache is the answer, and the third feature explains how the cache is filled: staggered cache warmup. Rather than running every cached query at once when the exporter starts, the warmup is spread out, so a restart does not produce a burst of load on the database.

That pairing is the most thoughtful thing in the feature list, because the failure mode it prevents is specific. An exporter with a hundred cached queries that fills them all at startup turns every deployment into a load test. Spreading the warmup means the exporter can be restarted freely without the database noticing.

The fourth feature is fully configuration-driven metrics, and the fifth is flexible metric mapping. Together they mean the metric is described in configuration, and the mapping from a query column to a Prometheus metric is also configuration. A new metric is a new configuration file, not a new binary.

The sixth and seventh are the multi-target mode and selective job scraping. Multi-target means one exporter process can hold several database targets and scrape them on one schedule, which is the deployment shape for a fleet. Selective job scraping means you can ask for one target rather than all of them, which matters when a single scrape of everything is expensive.

Then come the operational features: secret manager integration, so the credentials come from a secret store rather than from a file; TLS and basic authentication support, for the exporter's own endpoint; request rate limiting; live reload of the configuration without a restart; automatic metrics, meaning the exporter reports on itself; and built-in validation and a config check, so a broken configuration is reported rather than discovered at scrape time.

The config check and the live reload are the pair that a user will appreciate most in practice, because the alternative to both is restarting the exporter every time a query changes, and the exporter is often deployed as a single replica.

## The drivers, read off the dependency list

The module file is a good way to see what the exporter actually supports, because the driver libraries are the direct dependencies and each one is a database.

There is a driver for PostgreSQL, in two of them: the pure Go one and the standard library based one. There is a driver for MySQL, and a separate file in the repository for the MySQL specific TLS handling, with a counterpart file for builds that exclude it, which is the build tag mechanism rather than a runtime option. There is a driver for Microsoft SQL Server, and one for Oracle. There is a driver for ClickHouse, and one for Snowflake, and one for Vertica, which is a columnar analytical database with its own Go driver.

There is a driver for a SQL query language, from a project that is not a database but a query engine, and the file naming suggests the exporter can treat it as one. There is a driver that connects through a URL, which is the one that makes the database-agnostic claim work in practice: if you can express the connection as a URL, you can point the exporter at an engine that has no bespoke driver.

Then there is the cloud and infrastructure group. There is a client for the Google secret manager, a client for the AWS secrets manager, and a client for the AWS configuration, plus a client for the HashiCorp Vault API. Those are the three secret managers the feature list refers to, and each is a separate dependency because each has its own client library with its own authentication model.

There is the Kubernetes client, at three packages, the API types, the machinery, and the client itself. That is what the Kubernetes secrets example in the repository is for: pulling a database password out of a secret in the cluster rather than out of a file in the container.

There is the Prometheus client library, the client model, the common library with its shared helpers, and the exporter toolkit, which is the standard set of pieces that an exporter uses to serve the metrics endpoint with the right headers and the right build information.

And there are two small ones that are easy to overlook and are worth noticing. One is a configuration library that reads the environment, so the exporter can be configured entirely through environment variables, which is what container platforms prefer. The other is a YAML parser, at a version that is not the one most people expect, which is a sign of how carefully the dependencies are tracked in this project.

## One process, many databases

The multi-target mode is the feature that changes the deployment story, so it is worth working through what the repository layout says about it.

The top level has a job file, a target file, and a collector file, next to the exporter itself, the query handling, the metric handling, and the SQL layer. The names map onto the concepts: a job is a unit of work, a target is a database to run it against, and a collector is what runs the queries and produces the metrics.

There is a file for the warmup logic, one for the configuration reload, and one for the errors. The reload file comes with a test file next to it, as do the query handling and the exporter itself, which tells you that the two features most likely to break in production, the configuration reload and the query execution, are the two with unit tests.

Two generated files are also present, one for the drivers and one for a driver remapping table. Generated driver code is how a project with this many database engines keeps the driver list in one place instead of in a switch statement in the middle of the collector, and the remapping file is what maps a URL scheme to the right driver.

The job model then explains the features that mention jobs. In multi-target mode, one exporter holds several jobs, each with its own targets, its own queries, and its own cache. Prometheus scrapes the exporter on one endpoint, and the exporter decides internally which jobs to run, which is the selective job scraping feature.

That design is what makes the exporter usable at fleet scale. The alternative is one exporter process per database, each with its own configuration, its own scrape target in the Prometheus configuration, and its own deployment. With jobs inside one process, the number of Prometheus scrape targets stays small, the configuration is one file, and adding a database is a configuration change.

The cost is that the exporter becomes a process you cannot restart casually, which is exactly why the staggered cache warmup exists. If every job's cache is filled at startup, a restart of a single exporter with many jobs is a load event on every database it knows about.

## Configuration, secrets, and the self-check

The configuration directory in the repository and the examples directory tell you how the tool is meant to be used in anger.

The examples are seven, and each one is a configuration scenario rather than a code sample. There is a plain PostgreSQL example, and a Microsoft SQL Server one. There is an authentication-only example and a TLS-only example, and one with both. There is an example that reads its credentials from a Kubernetes secret. And there is one for Azure SQL Managed Instance.

That set is a decision about the security model. The exporter needs a database credential, and a database credential in a configuration file is a credential in a configuration file. The examples show the alternatives: a secret manager, a workload identity, and the plain case for development.

The documentation directory is in the repository, so the documentation site is built from it, and the readme's links to the general configuration page and to the full configuration reference are links into that directory. A project that keeps its configuration reference in the same tree as the code is a project where the reference is updated with the code.

Two of the thirteen features are about catching mistakes before they matter. There is built-in validation and a config check, so the exporter can be asked whether its configuration is valid before it is asked for metrics. And there is live reload of the configuration without a restart, so that a change to a query takes effect without the deployment that goes with it.

The two features interact in a way that is worth understanding. If the configuration can be reloaded at run time, then a bad edit can be loaded into a running process, which is why the validation and the check exist as separate capabilities. The check is what you run in a pipeline before the reload happens.

And the automatic metrics are the third piece of the operational story. An exporter that reports on itself tells you whether the last scrape succeeded, how long the queries took, and whether the cache is fresh, which is the difference between knowing that a database metric is wrong and knowing that the exporter is broken.

The security file in the repository root is the vulnerability disclosure policy, and the readme's support section asks people to check the discussions and the closed issues first, on the reasonable grounds that somebody else has probably already hit the same problem.

## The build, the container, and a Windows carve-out

The build system is inherited from the Prometheus exporter tradition, and the details are worth reading because they show how a project of this size handles its edges.

The build file starts with the Apache licence header from the Prometheus authors, dated 2015, which is a direct inheritance from the original implementation. Then there is a piece of logic that is unusual and immediately explains itself: to distinguish native Windows from the Windows subsystem for Linux, the build has to check how the path variable is separated, because it is a colon on the subsystem and a semicolon on native Windows, and the check is a string search for the semicolon in the path.

That is a small piece of portability code, and its presence tells you the project supports being built on Windows, which in turn explains two other things. The Go module includes a library for registering a program as a Windows service, so the exporter can run as a service on a Windows host rather than only in a container. And the build has a second target that produces a binary with the MySQL driver excluded, which is the tag mechanism that the two files for MySQL specific TLS handling correspond to.

The build tools are two: the Prometheus release tool, which builds and archives the binaries for a release, and a YAML processor, pinned to a specific version, used by the configuration tooling. Both are pinned to exact versions, which is the convention that keeps a release reproducible.

The default target runs formatting, then the build, then the tests, and the tests run in short mode, which skips the slow ones. The style target is a formatting check that fails the build if any file is not formatted, and there are separate targets for vetting and for formatting.

The container is a two stage build on the Prometheus builder image and the Prometheus busybox base, and it is three lines of interest. The final image copies in the single binary, it exposes the metrics port, and it runs as an unprivileged user rather than as root.

The maintainer label on that image still names the Prometheus authors, which is a leftover of the inheritance and a small inconsistency in an otherwise tidy file. There is a second Dockerfile for multi-architecture builds, and a packaging directory alongside a Helm chart, so the distribution story covers a container, a chart, and a binary for people who do not want either of the first two.

## Conclusion

sql_exporter fits an operations team that wants database metrics without writing a custom exporter for every engine, and a team that already runs a fleet of databases and wants one binary that scrapes them all. It does not fit a team that wants the metrics to be defined in code and versioned with the service, because the definition here lives in configuration files. Verify first that your database has a driver in the supported list, that the queries you plan to run are cheap enough to run on every scrape, and that you understand the cache and warmup settings, since a query that is slow to run against a large table will either slow the scrape or leave the cache stale.

## FAQ

### What does the sql_exporter project do?

It is a database-agnostic exporter that runs queries against your databases and exposes the results in the Prometheus format. The metric definitions, the queries, and the connections are all configuration, so one binary and one configuration format cover every database engine that has a driver.

### Which databases does sql_exporter support?

The direct dependencies in the module file name the drivers: PostgreSQL through two of them, MySQL, Microsoft SQL Server, Oracle, ClickHouse, Snowflake, Vertica, a SQL query engine driver, and a driver that connects through a URL, which is what makes the database-agnostic claim work for engines without a bespoke driver.

### What is the multi-target or jobs mode in sql_exporter?

It is a mode where one exporter process holds several jobs, each with its own targets, queries and cache, and Prometheus scrapes the exporter on a single endpoint. Individual jobs can be scraped selectively, and it means the number of scrape targets in the Prometheus configuration stays small as the number of databases grows.

### How does sql_exporter handle database credentials?

Through secret manager integration, with clients for Google secret manager, the AWS secrets manager, and the HashiCorp Vault API, plus a Kubernetes client for reading secrets from the cluster. The examples directory shows the scenarios, including one for Azure SQL Managed Instance.

### What is the cache and the staggered warmup in sql_exporter?

By default the exporter runs its queries at scrape time, synchronously, and the cache is optional. The staggered warmup spreads the initial cache fill out over time rather than running everything at startup, so that restarting an exporter with many jobs does not produce a burst of load on every database it knows about.

## Sources

- [burningalchemist/sql_exporter on GitHub](https://github.com/burningalchemist/sql_exporter)
- [License: MIT](https://github.com/burningalchemist/sql_exporter/blob/master/LICENSE)
- [Project website](https://burningalchemist.github.io/sql_exporter/)
- [README](https://github.com/burningalchemist/sql_exporter/blob/master/README.md)
- [Releases](https://github.com/burningalchemist/sql_exporter/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/burningalchemist-sql-exporter
