Event-Driven Architecture
Every action in lim starts with an event. Bank transactions, invoices, manual entries, MCP tool calls — all are events that flow through a unified pipeline.Event Flow
Ingestion Layer
Events enter lim through multiple channels:
Each ingestion adapter normalizes the raw data into a common event format.
Event Normalization
All events are normalized to a common structure before processing:The Event Table
Every event is persisted in theevent table before processing. This serves three purposes:
- Audit trail. Every business event is recorded permanently, even if it’s later reversed or modified.
- Replay capability. Events can be replayed to reconstruct the ledger state at any point in time.
- Debugging. When a journal entry looks wrong, you can trace it back to the original event.
Event Lifecycle
Event Graph
Events can be linked to form a directed acyclic graph (DAG). This captures causal relationships:event_graph table stores these edges. This enables:
- Traceability. “Why does this journal entry exist?” Follow the event chain back to the originating business event.
- Impact analysis. “If I reverse this invoice, what else is affected?”
- Compliance. Auditors can see the complete chain from source document to financial statement.
PG LISTEN/NOTIFY
lim uses PostgreSQL’s built-inLISTEN/NOTIFY mechanism for real-time event processing:
- Low latency. Events are processed within milliseconds of insertion.
- No external dependencies. No Kafka, no Redis, no RabbitMQ. Just PostgreSQL.
- Transactional consistency. NOTIFY is sent only when the transaction commits.
Polling Fallback
LISTEN/NOTIFY is not durable — if the subscriber is down when a notification fires, it’s lost. lim uses a polling fallback: