Skip to main content

How it works

The Lead domain has no tables per integration type (transactions, form_responses, etc.). Enriched data is derived from events and stored as memories by the Memory Updater Lambda.
Event (immutable, append-only)     →     Memory (derived, queryable)
  Source of truth                              Current structured state
  Full payload + raw_payload                   O(1) access by key
  Auditable history                            Ready for templates and AI
If a memory is corrupted or derivation logic changes, just replay events to rebuild. The event is the source of truth. New integration = update the Memory Updater Lambda. No migration, no new table.

Memory schema

Memory
├── lead_organization_id  UUID, FK → LeadOrganization
├── memory_type           ENUM (fact, preference, interest, purchase, support, behavioral, campaign, form)
├── key                   VARCHAR(255)
├── value                 JSONB
├── confidence            REAL (0.0 - 1.0)
├── source                ENUM (agent_inferred, user_declared, system_computed, event_derived)
├── source_event_ids      LIST — IDs of the Events that generated/updated this memory
├── created_at            TIMESTAMPTZ
├── updated_at            TIMESTAMPTZ
└── expires_at            TIMESTAMPTZ, nullable
source_event_ids provides full traceability from a memory back to the events that produced it. Memories that overwrite (e.g., last_transaction) contain a single event ID. Memories that aggregate (e.g., product:whey_1kg with purchase_count: 5) contain all contributing event IDs. UNIQUE on (lead_organization_id, memory_type, key) — enables upsert.

Memory Types

TypeDescriptionKey examples
factFactual informationfamily, location
preferenceCommunication or behavior preferencesprice_sensitivity, payment_method
interestInterest in a product or categorycategory:supplements, product:creatina
purchasePurchase history and patternslast_transaction, product:whey_1kg
supportSupport historyticket:T-456
behavioralObserved behavior patternslast_conversation, response_pattern
campaignCampaign interaction historycampaign:camp_whey_recompra
formForm responsessat_survey_2026:how_did_you_find_us

Template variable resolution

Dispatch templates resolve variables from Lead (profile) and Memory (enriched data): Template:
"Hi {{lead.name}}, I noticed you purchased {{purchase.last_transaction.product_name}}
 for R${{purchase.last_transaction.amount}}.
 You found us through {{form.sat_survey_2026:how_did_you_find_us.answer}}, right?"
Resolution:
VariableQuery
lead.nameAurora: Lead.name
purchase.last_transaction.product_nameDynamoDB: SK="purchase#last_transaction" → value.product_name
purchase.last_transaction.amountSame item → value.amount
form.sat_survey_2026:how_did_you_find_us.answerDynamoDB: SK="form#sat_survey_2026:how_did_you_find_us" → value.answer
Each variable = 1 DynamoDB GetItem. No scans, no joins.