How Strimz fits together
A 90-second tour of the six processes and what each one does.
Strimz runs as six processes. You only ever call one of them directly, the API. Knowing what the other five do is mostly useful when something breaks and you need to pick the right log file.
Architecture at a glance
Requests hit apps/api. It writes to Postgres and pushes background
work onto Redis. When a payer submits an EIP-3009 or EIP-2612
signature, the relayer module inside apps/api signs and broadcasts
the on-chain transaction with a KMS-managed key. The scheduler runs
the cron side of the system: subscription charges, retry sweeps, and
the webhook delivery queue. The indexer watches Arc and writes the
events it sees back to Postgres. The agent reads from Postgres but
never signs anything.
The six processes
apps/api
Nest + Fastify. Validates input with Zod, writes to Postgres, fires events. Also hosts the relayer that broadcasts payer-signed meta-transactions. The relayer's key is held by a KMS provider; the API process never sees raw bytes.
apps/indexer
Go process polling Arc RPC. Decodes contract events, projects them into Postgres tables. Re-derives state from chain history.
apps/scheduler
Nest + BullMQ. Runs cron jobs (subscription charges and retry sweeps) and the webhook delivery queue. On startup it decrypts the webhook signing secrets out of Postgres so the delivery worker can read them from Redis.
apps/agent
The AutoPay Agent. Hourly + daily crons. Recovery emails, cashflow digests, anomaly detection, CCTP routing. Holds no key.
apps/web
Next.js. Marketing site, merchant dashboard, hosted checkout, public storefronts, and these docs all live in the same app.
packages/contracts
Foundry workspace. Payments and Subscriptions are immutable. Registry, FeeCollector, and TokenWhitelist are UUPS-upgradeable. Every contract uses ERC-7201 namespaced storage.
Repository layout
Where to look when something is wrong
Each process owns a well-defined slice of behaviour. Knowing which slice covers the symptom is usually enough to pick the right log.
| Symptom | Process to check |
|---|---|
| API returning 5xx | apps/api logs |
| Subscriptions not charging on schedule | apps/scheduler (sweeper tick + worker) |
| Webhooks failing or stuck retrying | apps/scheduler (delivery worker) |
| New on-chain payment not in dashboard | apps/indexer (cursor caught up?) |
| Merchant not getting daily digest | apps/agent (cashflow cron logs) |
CCTP bridge stuck in bridge_initiated | apps/agent (Circle attestation poller) |
What you don't need to think about
Built-in guarantees
- On-chain idempotency. The contract's
usedAttempts[id]mapping makes every charge attempt safe to retry without duplication. - Webhook delivery retries. The scheduler retries on a backoff schedule of 1m, 5m, 30m, 2h, and 12h. If all five attempts fail, you get an email and the endpoint can auto-disable. - Reorg protection. The indexer waitsCONFIRMATIONSblocks (default 5) before projecting an event. Arc's finality makes short reorgs unlikely; the margin is there anyway.
Want to dig deeper?
Resources
The objects you'll interact with: what they mean, when they exist, what their lifecycles look like.
Idempotency
How Strimz keeps retries safe at every layer: the API, the scheduler, and the contracts.
On-chain architecture
The contract suite. What's immutable, what's upgradeable, why we drew the line where we did, and how to verify the deployment yourself.
Modes of failure
What can go wrong, what you'll see when it does, and what Strimz does about it automatically.
