Skip to content

API Conventions

The public API follows a few constructor and factory rules so a new primitive feels like the existing ones. Follow them when you add a pattern or component.

Patterns take a positional name

A pattern is the object user code calls directly, such as Lock, CircuitBreaker, or a RateLimiter built from a factory. Its first argument is a positional name that identifies the instance and drives its config prefix:

Lock("cart")
CircuitBreaker("payments")
RateLimiter.sliding_window("api", limit=100, window=60)

The name comes first because it is the one argument every call sets. Everything else (backend=, tuning fields) is keyword-only with a default.

Components take the provider first, name keyword-only

A component or registry is app-level wiring passed to uses=, such as Coordination, Cache, or RateLimiterRegistry. Its first positional is the provider or backend it wraps. The registration name is keyword-only and defaults to "default":

Coordination(redis)
Cache(redis)
RateLimiterRegistry(redis, name="api")

Most apps register one component per kind, so the default name keeps the common case silent. Name a second instance only when two of the same kind coexist.

Algorithms use factory classmethods

When a pattern has more than one algorithm, expose each as an explicit factory classmethod rather than a kind= argument. The classmethod names the algorithm and takes only the fields that algorithm needs:

RateLimiter.sliding_window("api", limit=100, window=60)
RateLimiter.token_bucket("api", rate=10, capacity=20)
CircuitBreaker.consecutive_count("payments", error_threshold=5)

The bare constructor stays available for a pre-assembled config object (from YAML or a pydantic-settings tree), but the factory is the path most callers take.