HatchedDocs
Concepts

Rule engine

The deterministic two-phase pipeline that converts events into effects.

The rule engine is the heart of Hatched. Every event you send goes through the same pipeline; every effect the buddy accumulates is the output of that pipeline.

The two-phase contract

  1. Compute phase — read-only. Given the current buddy state and the incoming event, the engine computes what would change: coin increments, skill increments, badges newly eligible, token deltas, streak ticks.
  2. Apply phase — transactional. Opens a single database transaction, takes a pessimistic_write lock on the buddy row, writes every computed effect, commits atomically. If any step throws, everything rolls back.
  3. Post-transaction — non-atomic side effects: progression counters, evolution readiness check, webhook emission.

Why this split

Two properties fall out of the contract:

  • Idempotency — the same event_id produces exactly one effect even if retried.
  • Race-freedom — concurrent events for the same buddy serialise on the row lock, so two overlapping lessons don't both award the same badge.

Two ingestion paths — by design

  • POST /events — standard ingestion. The rule engine owns the decision.
  • POST /coins, POST /skills, POST /badges/:id/award, POST /tokens — administrative override. Every write still funnels through the same transactional services, so ledger invariants are preserved.

This is intentional. Don't try to collapse them into a single endpoint.

Unknown events

Events not declared on the customer's config version:

  • Type in EVENT_COUNTER_MAP → increments the canonical column.
  • Type not in the map → atomically upserts into progression_metrics.custom_counters via a jsonb_set update. Downstream handlers still evaluate.
  • Type neither in the map nor declared → same as above, plus a warning log. Never dropped.

Observability

Every event carries a requestId that follows it through the rule engine, into effect ledger entries, and out into webhooks. See Observability for the incident triage workflow.