Skip to main content

natsio-counters

Distributed counters over JetStream counter streams (ADR-49), mirroring orbit.go/counters. Distribution natsio-counters, imported as natsio.counters. Zero runtime dependencies beyond natsio. Pre-1.0, no API-stability promises.

Requires nats-server 2.12+ (the allow_msg_counter stream feature).

What it is

A counter stream is a normal JetStream stream created with allow_msg_counter. Every subject the stream captures becomes an independent, arbitrary-precision counter. Incrementing is an ordinary publish carrying a Nats-Incr header; the server folds the delta into a running total, stores it as the subject's latest message, and returns the new value in the PubAck — so a bare add needs no follow-up read.

Python int is itself unbounded, so it is used directly for both deltas and values — no big-integer wrapper.

Usage

import natsio
from natsio.counters import CounterConfig, create_counter, get_counter

nc = await natsio.connect("nats://localhost")
js = nc.jetstream()

# Create a counter stream (allow_msg_counter + allow_direct are forced on).
counter = await create_counter(js, CounterConfig(name="COUNTS", subjects=["events.>"]))
# ...or bind an existing one:  counter = await get_counter(js, "COUNTS")

# Increment / decrement — returns the new running total, straight from the PubAck.
await counter.add("events.orders", 1)      # -> 1
await counter.add("events.orders", 10)     # -> 11
await counter.add("events.orders", -4)     # negative deltas are fine  -> 7
await counter.add("events.orders", 0)      # zero is a valid no-op increment

# Read a single counter's current value.
value = await counter.load("events.orders")          # -> 7

# Full entry: value + most-recent increment + source history (aggregation only).
entry = await counter.get("events.orders")
print(entry.value, entry.incr, entry.sources)

# Enumerate many counters in one batch Direct Get (wildcards allowed).
async for entry in counter.get_multiple(["events.>"]):
    print(entry.subject, entry.value)

API

Symbol Purpose
create_counter(js, config) Create a counter stream and return its Counter.
get_counter(js, name) Bind an existing counter stream by name.
counter_from_stream(js, stream) Wrap an already-fetched counter Stream (no round-trip).
Counter.add(subject, delta) -> int Increment/decrement; returns the new total.
Counter.load(subject) -> int Current value of one subject's counter.
Counter.get(subject) -> CounterEntry Value + last increment + sources.
Counter.get_multiple(subjects) -> AsyncIterator[CounterEntry] Batch/wildcard enumeration.
CounterConfig Counter-stream configuration.
CounterEntry subject, value, sources, incr.

Errors (all subclass natsio.jetstream.JetStreamError): CounterNotEnabledError, DirectAccessRequiredError, CounterNotFoundError, CounterSubjectNotInitializedError, InvalidCounterValueError.

ADR-49 wire contract

Pinned by the wire-contract tests and exported as constants:

  • Increment header Nats-Incr (COUNTER_INCREMENT_HEADER) — a base-10 integer of any size, optional leading sign. A counter stream rejects any publish without it (message counter increment is missing).
  • Sources header Nats-Counter-Sources (COUNTER_SOURCES_HEADER) — server-set JSON {source_stream: {subject: contribution}}; present only on aggregating counters.
  • Stored payload {"val": "<int-as-string>"} — the value is a string so it survives languages whose JSON numbers cap at 2^53.
  • PubAck carries the new total in its val field (fast feedback, no Get).

Notes: allow_msg_counter can be set only at stream creation (it is read-only afterwards) and is incompatible with per-message TTLs and message schedules, so CounterConfig intentionally does not expose those knobs. Reads use Direct Get, so allow_direct is required (and forced on by create_counter).

Example

A runnable script is at examples/basic.py — start a server with just server, then:

python extensions/natsio-counters/examples/basic.py

Metadata

Release files for natsio-counters 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for natsio-counters 0.1.2
File Size Uploaded Provenance
natsio_counters-0.1.2.tar.gz 8.0 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for natsio-counters 0.1.2
File Interpreter ABI Platform
natsio_counters-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 18.0 kB

Release files / natsio_counters-0.1.2.tar.gz

Download URL natsio_counters-0.1.2.tar.gz
Size 8.0 kB
Tags Source
SHA-256 checksum
How to use checksums
fcb0c66fd77b17c2918ed3846a88809338039dd8d19a3ab4959153f4777b9146
BLAKE2b-256 checksum
How to use checksums
12bc2a95599f92973bf06d5531b52797d768be612410c28828056b82f85b1a28
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Release files / natsio_counters-0.1.2-py3-none-any.whl

Download URL natsio_counters-0.1.2-py3-none-any.whl
Size 10.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7f48582da21a366a919f852af294be8a3f8046926671cb1d85d147936e44dd3c
BLAKE2b-256 checksum
How to use checksums
ca6bd5b960b603fd0a289452fd11eab3233094e5f7196c49edd545fa8e68c68b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

Security for natsio-counters 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for natsio_counters-0.1.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 22, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page