# OpenMeter: metering, entitlements and usage billing on Kafka and ClickHouse

> OpenMeter turns raw usage events into metered values, feature access decisions and invoices. It is API-first, deliberately not an operator UI, and still shipping beta releases.

**openmeterio/openmeter** — Metering and Billing for AI, API and DevOps. Collect and aggregate millions of usage events in real-time and enable usage-based billing.

- Repository: https://github.com/openmeterio/openmeter
- Website: https://openmeter.io
- Stars: 2,377 · Forks: 224
- Language: Go
- License: Apache-2.0
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/openmeterio-openmeter

## From raw events to an invoice, with three consumers in between

The architecture is easiest to understand as a pipeline with three consumers of the same ingested event. Events arrive as CloudEvents, get attributed to a customer, are aggregated in real time into a metered value, and that value is then read by three different subsystems: metered queries for reporting, entitlement calculation for access decisions, and rating for the invoice.

Input is CloudEvents, which is the decision that makes the rest composable. You post a specversion, a type, an id, a source, a subject and a data payload, and nothing in that shape is OpenMeter-specific. A Go service using the official SDK and a Python service posting raw JSON with curl produce identical results. The README's quickstart demonstrates exactly that equivalence with three separate client examples.

The storage story underneath is visible in the dependency tree rather than the prose. Kafka via both Sarama and Watermill for ingestion, ClickHouse for aggregation, PostgreSQL for transactional state, Redis for deduplication, and Svix for webhooks. The `go.mod` also pulls in `entgo.io/ent` for the schema layer, `gobl` for billing documents, `bhmj/jsonslice` for JSON path extraction inside event data, and `ch-go` for ClickHouse's native protocol.

The `benthos-collector.Dockerfile` in the repository root is the piece that connects this to existing infrastructure: it implies a supported path for collecting events from systems that are not OpenMeter clients at all, which is how a company with an existing Kafka estate would feed it.

## Bringing up the evaluation stack in three commands

The quickstart is a local evaluation stack, and the README is explicit about that distinction. You clone the repository, change into the `quickstart/` directory and start everything:

```sh
git clone https://github.com/openmeterio/openmeter.git
cd openmeter/quickstart
docker compose up -d --wait
```

The stack runs the OpenMeter API and workers alongside Kafka, ClickHouse, PostgreSQL, Redis and Svix, all on `latest` OpenMeter images. The API listens on port 48888, and the stack ships with one meter already defined, called `api_requests_total`.

Every example client then does the same two-step thing: send one `request` event, then poll the meter's query endpoint until the value reaches 1. The bash example is the shortest, and the polling loop is not decoration. Event processing is asynchronous, so a successful run ends with a metered value of 1 a second or more after the POST returned 200:

```sh
curl -sS -o /dev/null -w '%{http_code}\n' \
  -X POST http://localhost:48888/api/v1/events \
  -H 'Content-Type: application/cloudevents+json' \
  --data-raw '{
    "specversion": "1.0",
    "type": "request",
    "id": "readme-curl-1",
    "source": "readme",
    "subject": "readme-curl",
    "data": { "method": "GET", "route": "/hello" }
  }'
```

The SDKs are equivalent. TypeScript installs `@openmeter/sdk` alongside `tsx`, and Python needs `python -m pip install --pre openmeter` because the Python SDK is in preview, which is a small but real signal about the SDK maturity spread across languages.

## Meters, entitlements and pricing are three separable pieces

The README is unusually clear about scope, and the fit table is worth reading before anything else. It says what OpenMeter is best for: products with usage-based or hybrid pricing, prepaid credits, or usage limits that need one source of truth for consumption. It says what it is not: a bundled operator UI, a payment processor, a tax engine, or a general-purpose accounting system. And it says that if you only need fixed recurring subscriptions, a direct payment-provider integration is usually simpler.

That last sentence is the most useful thing in the document, because it tells you when not to use it.

Within its scope there are five capability groups. Meter usage covers ingesting CloudEvents, attributing them to customers, aggregating in real time, and querying by time window or dimension. Product modelling covers versioned plans, features, add-ons, and flat, recurring, per-unit, tiered, package or dynamic prices. Access control calculates feature access and usage-limit balances with one-time or recurring entitlement grants. Billing rates flat and usage-based charges, manages credit balances and subscription changes, and runs the invoice lifecycle. Integration is the REST API, JavaScript, Python and Go SDKs, webhooks, and external invoicing providers.

The credit balance and entitlement machinery is what separates this from a metering library. A meter tells you how much was consumed. An entitlement tells a customer-facing service whether to allow the call. Keeping both on the same aggregated number is the design decision that makes prepaid credits and hard usage limits possible without two sources of truth disagreeing.

## Beta releases, and how the composable-stack pitch is sold

The three most recent releases are v1.0.0-beta.233 from 2026-09-18, v1.0.0-beta.232 from 2026-08-04 and v1.0.0-beta.231 from 2026-07-14. The numbering is the useful signal here: two hundred and thirty-three beta builds of a 1.0.0 means the API surface is still moving, and the README says so in the maturity row, warning that releases are beta and can include breaking changes.

Against that, the README also claims the metering engine has run in production for years and processed billions of usage events. Both statements are compatible: a hosted product can run a mature engine while the open-source release stays in beta. But the distinction matters for anyone self-hosting, because what you are adopting is the open-source release, not the hosted service's internal history. The README's own advice applies: review the releases and the migration guides in `docs/migration-guides/` when upgrading.

That is the whole upgrade story in one sentence, and it is a legitimate answer rather than a dodge, given the release volume.

The composability pitch is the other thing worth interrogating. You can adopt the whole path from event to invoice, or only the metering half and keep your existing billing system. Whether that modularity is real depends on how cleanly the boundaries hold, and the repository layout gives a hint: `api/` with versioned directories and OpenAPI generation targets, `pkg/`, `cmd/` for separate binaries, `collector/`, `app/`, and an `openmeter/` directory alongside them. The `Dockerfile` builds three binaries, `openmeter`, `openmeter-sink-worker` and `openmeter-balance-worker`, so ingestion, aggregation and balance work are separate processes that scale independently.

## The infrastructure bill is the real cost line

An honest evaluation of OpenMeter has to price the dependency list, because Kafka, ClickHouse, PostgreSQL, Redis and Svix is five stateful services to operate before any metering happens. ClickHouse in particular is a columnar database with its own memory profile, and Kafka carries its own partition and retention decisions.

The root `docker-compose.yaml` shows how the pieces are layered. Each service extends a shared `docker-compose.base.yaml`, and several sit behind Compose profiles rather than starting by default: Redis under the `redis` profile for deduplication, PostgreSQL under the `postgres` profile for credit, Svix under the `webhook` profile, and the Kafka and ClickHouse UIs under `dev`. That is a thoughtful way to keep a local stack small, and it is also a hint at which subsystems are optional.

The Go toolchain is not trivial either. `go.mod` declares Go 1.27, and the `Dockerfile` builds against golang:1.27.1-alpine3.23 with CGO enabled and a static musl link against librdkafka for the Kafka client, which is why the image copies `xx` in for cross-compilation helpers and runs `xx-verify` on the output.

The scale claim is worth pairing with this. Millions of events in real time is exactly the regime where Kafka and ClickHouse earn their keep and exactly the regime where a simpler stack would not survive. If your product meters thousands of events a minute rather than millions, that infrastructure is overhead you are paying for a headroom you do not need.

## Where a reader should start, and what to verify first

The README is a good index and stops at the point where decisions begin. It hands off to the documentation at openmeter.io/docs, to the API reference under openmeter.io/docs/api/open-source, and to the migration guides. The repository carries `AGENTS.md`, `CLAUDE.md`, a `.mcp.json`, `.cursor`-style agent configuration directories and a `codegraph.json`, which tells you the project has been developed with coding assistants in the loop.

Licensing is Apache-2.0 with a `LICENSE` file at the root, the permissive end of the scale, so self-hosting and modification carry no copyleft obligation. The last push was on 2026-09-18, the same day as the newest beta release.

Three things to verify before committing. First, whether the beta numbering bites you: read a release or two and the migration guides to see whether API changes are routine. Second, the deduplication behaviour, since a usage number that double counts on a retried event is a billing dispute, and Redis is listed as the deduplication layer in the compose comments. Third, the metering semantics for your own event shape, because a CloudEvents `subject` is what usage gets attributed to and a mis-mapped subject silently attributes spend to the wrong customer.

The quickstart answers all three in about ten minutes: run the stack, post one event, poll until the value resolves, and read what the meter actually counted. That loop is the fastest honest test of whether this fits your pricing model.

## Conclusion

OpenMeter is built for a specific and common shape of problem: a product priced on consumption where the number has to be right before the customer complains, and where the number is assembled from events emitted by several services. Kafka plus ClickHouse is a deliberate answer to high write volume and time-window queries, and the CloudEvents input means you do not have to adopt its client libraries. It is the wrong choice for flat recurring subscriptions, which the README itself says a payment provider integration handles more simply. Bring up the quickstart stack, send one event, watch the meter resolve asynchronously to 1, then read `docs/migration-guides/` before pinning a beta version.

## FAQ

### What is an OpenMeter?

OpenMeter is open-source monetization infrastructure for AI, API and usage-based products, written in Go and licensed Apache-2.0. It ingests CloudEvents, attributes usage to customers, aggregates it into metered values in real time, calculates feature entitlements, and runs usage-based billing through to invoices. The README is explicit that it is not an operator UI, payment processor, tax engine or accounting system.

### How does usage-based billing work in OpenMeter?

You define meters that aggregate events, model products and prices as versioned plans with flat, recurring, per-unit, tiered, package or dynamic prices, then assign subscriptions to customers. Rating turns metered values into charges, credit balances and prepaid entitlements are managed against the same numbers, and the invoice lifecycle handles the rest. Entitlements let a customer-facing service check both feature access and remaining usage-limit balance from one source.

### Where can I find the OpenMeter API docs and SDKs?

The README links the API reference at openmeter.io/docs/api/open-source and the documentation at openmeter.io/docs. SDKs exist for JavaScript, Python and Go, published as `@openmeter/sdk`, `openmeter` on PyPI (install with pre-releases, since it is in preview) and as a Go module. The API is versioned under `/api/v1` on the local stack.

## Sources

- [License: Apache-2.0](https://github.com/openmeterio/openmeter/blob/main/LICENSE)
- [openmeterio/openmeter on GitHub](https://github.com/openmeterio/openmeter)
- [Project website](https://openmeter.io)
- [README](https://github.com/openmeterio/openmeter/blob/main/README.md)
- [Releases](https://github.com/openmeterio/openmeter/releases)

---

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