Skip to content

Athomic Capability Map — "Look here before you build"

Purpose: a single index of which cross-cutting capability lives in which src/nala/athomic/ module, and the entry point to reuse it. This exists to enforce DRY: before writing any infrastructure code (retry, cache, lock, backoff, secrets, …), find it here and reuse/extend it instead of reinventing it inside your consumer module.

Rule of thumb: cross-cutting concerns belong to their owning athomic module and are injected at the composition root (DIP). If the capability is missing, add it to the owning module (generic + reusable), never ad-hoc in the consumer. The code is the source of truth — this table is a pointer and may lag; verify the entry point exists before relying on it.

How to use this map

  1. Name the concern (e.g. "retry a flaky call", "rate limit", "cache result").
  2. Find its module + entry point below.
  3. Reuse the factory/protocol; inject it via the composition root.
  4. If it doesn't exist, implement it in that module so every other module gets it for free — then add a row here.

Resilience — resilience/

Reach for these before writing any retry/timeout/throttle/failover logic.

Need Entry point Notes
Retry a failed call (exp. backoff + jitter) retry.RetryFactory → RetryHandler tenacity wait_random_exponential; do not use the @retry decorator in DI code (hides a Service Locator)
Retry + circuit breaker as one pipeline ResilienceOrchestratorFactory.create(...) → ResilienceOrchestrator.execute(fn) canonical way to protect a backend call; CB(outer) → retry(inner) → fn
Trip/fail-fast on a failing dependency circuit_breaker.CircuitBreakerFactory one service, many named circuits — use distinct names per backend for failure isolation
Delay sequencing inside your own poll/consume loop backoff.BackoffFactory → BackoffHandler (wait()/reset()) stateful sequencer, not a call wrapper — wrong tool for "retry a call"
Fallback chain (try A, then B…) fallback.FallbackChain / fallback_handler
Cut tail latency on a replicated idempotent backend hedging.HedgingFactory → HedgingHandler / @hedge(idempotent=True) races a speculative backup after a fixed/latency-percentile delay; first success wins, losers cancelled. Only for idempotent calls (guardrail enforced). Layer inside retry/CB (wraps the raw call); point bulkhead_policy at a bulkhead to bound hedged load
Limit concurrency (isolation) bulkhead.bulkhead / BulkheadFactory
Rate limiting rate_limiter (rate_limited, RateLimiterProtocol)
Per-call / total timeout timeout (decorators, controller)
Adaptive concurrency / throttling adaptive_concurrency, adaptive_throttling
Distributed lock (mutual exclusion) locking.LockingFactory / LockingProtocol degrades to in-process when disabled
Leader election / exclusive lease leasing.LeaseFactory / LeaseManager
Idempotent execution idempotency.idempotent / protocol
Distributed sagas (compensations) sagas (builder/manager)
Workload sharding sharding.ShardingFactory
Hardware/VRAM admission guard resource_guard
Backpressure backpressure.BackpressureFactory / BackpressureManager

Observability — observability/

Need Entry point
Structured logging get_logger(name) (Loguru)
Tracing spans get_tracer(name), SpanKind, StatusCode
Prometheus metrics observability/metrics/... (declare in metrics/usage/)
Health checks observability health hooks

Database — database/

Need Entry point
Resolve KV / Vector / Doc / Graph stores ConnectionManager (injected)
KV store KVStoreFactory / KVStoreProtocol
Vector store vector factory / VectorStoreProtocol
Document DB (Mongo/Beanie) DocumentsDatabaseFactory / DocumentDBManager
Graph (Neo4j) GraphDatabaseFactory / GraphManager
Relational (Postgres) RelationalDatabaseFactory / RelationalManager
Relational tenant isolation (Postgres RLS) database/relational/rls.py: tenant_rls_policy_sql(...) for the canonical deny-all-on-empty policy DDL (put in your migration); per-transaction GUC stamping is auto-installed by PostgresRelationalClient when context.multi_tenancy_enabled + rls_enabled (no call-site changes); bypass_rls() for auditable migrations/admin. The 4th context-aware member alongside Graph/Vector/KV.
Outbox pattern database/outbox

Security — security/

Need Entry point
Secrets (Vault/GCP/AWS) SecretsFactory / SecretsManager
Auth (authN) AuthProviderFactory
Authorization (authZ) — RBAC or ReBAC, switchable security/auth/authz: build_authorization_provider(settings, …) → AuthorizationProvider (check/list_objects/expand). One setting authorization.provider flips rbac (roles→permissions) ↔ rebac (relation tuples: direct/union/tuple-to-userset, default-deny) with zero call-site changes. ReBAC store: embedded (in-memory/KV, no infra) or openfga (prod). mode (disabled/dry_run/enforce) orthogonal. The requires(...) route guard is provider-agnostic.
Crypto (Fernet) CryptoProviderFactory

Integration — integration/

Need Entry point
Kafka produce/consume MessagingManagerFactory / MessagingManager
Service discovery (Consul) ServiceDiscoveryFactory / ConsulClientFactory
Remote config providers SettingsProviderFactory
Background tasks TaskBrokerFactory

HTTP — http/

Need Entry point
Resilient HTTP client http factory (composes ResilienceOrchestrator)

AI / ML — ai/

Need Entry point
Embeddings EmbeddingFactory / EmbeddingManager
Feature engineering platform FeaturePlatformFactory (see ai/features deep-dive in CLAUDE.md)
LLM access LLMFactory
RL decision loop ReinforcementLearningFactory
Normalize an observation vector (online MinMax/Z-Score, per-key persisted stats) ai/normalization — NormalizerFactory + OnlineStatsAccumulator + NormalizationStateStore; decorate an encoder with NormalizingFeatureEncoder. For per-feature-column scaling inside the AOT platform use ai/features MinMaxTransformation/StandardScalerTransformation instead
Agents / cognition AgentFactory / CognitiveFactory

Other infrastructure

Need Module / entry point
Caching, compression, uvloop performance/ (CacheFallbackFactory, CompressionMiddlewareFactory)
Serialization serializer/ (SerializerFactory)
Event bus events/ (EventBusFactory)
Temporal workflows workflows/ (WorkflowClientFactory)
Stream processing streaming/ (StreamingServiceFactory)
Plugin loading plugins/ (PluginManager)
Settings (Dynaconf + Pydantic) config/ (get_settings())

When the capability is missing

  1. Confirm it truly doesn't exist (grep the module + this map).
  2. Implement it in the owning module, generic and reusable, with a factory and/or Protocol (Factory Rules + DIP — see solid-rules.md).
  3. Inject it at the composition root; never call the factory from business logic.
  4. Add a row here so the next person reuses it.

See also: design-patterns.md, solid-rules.md, code-smells.md, and the Module Map in CLAUDE.md.