04 Architecture¶
Source page: 04-architecture.html
4. Architecture summary (v1)¶
ACQUISITION PLATFORM ACTIVATION
County/recorder ──┐ ┌─────────────────────────────┐ ┌──► Mail house API
Permit portals ───┼──►│ Phoenix (Elixir umbrella) │ ├──► Ad audiences
NOAA storm data ──┤ │ GraphQL │ REST │ Channels │ ├──► Email drips
Enrichment APIs ◄─┤ │ ┌───────┐ ┌────────┐ ┌─────┐ │ └──► Canvass lists
(segment-gated) │ │ │ CRM & │ │ Autom. │ │ AI* │ │
│ │ │ sales │ │ engine │ │layer│ │ CRM VALVE
Website snippet │ │ └───────┘ │(ObanPro)│ └─────┘ │ engagement-triggered
│ │ │ ┌────────────────────────┐ │ promotion + outcome
▼ │ │ │ Prospect data engine │ │◄──► sync (built-in CRM
RudderStack + ─┼──►│ │ ingest·hygiene·segment │ │ or external, e.g.
PostHog (self- │
hosted heatmaps) │ │ └────────────────────────┘ │ JobNimbus API)
│ │ PubSub · ETS/Cachex │
│ └───────────┬──────────────────┘
│ │
│ ┌────────────▼─────────────────┐ ┌────────────┐
└─►│ PostgreSQL + TimescaleDB │ │ S3 / CDN │
│ + PostGIS │ │ OpenSearch │
│ · CRM system of record │ └────────────┘
│ · prospect warehouse (schema- │
│ isolated; parcels, storms, │
│ lineage, suppression) │
│ · event log (transactional) │
│ · Oban queues · pgvector │
│ · analytics + cont. aggregates│
└───────────────────────────────┘
Webhooks (Twilio, Stripe, suppliers, measurements) ──► Phoenix
Deferred by trigger: Kafka/Redpanda · ClickHouse
*AI layer = local purpose-tuned LLM served by vLLM (GPU pool) + pgvector
- Umbrella application, modular by OTP app — Core CRM, Automation Engine, AI Layer share one deployment initially, splittable later without rewrites.
- Automation engine isolated by process — workflow executions run under their own supervision tree so runaway automations never degrade API latency.
- All state changes write to the event log in the same transaction — automations, audit, and projections consume one log via cursors and never disagree; the tracking firehose is kept on a separate RudderStack path.
- One Absinthe schema is the API source of truth — mobile, web islands, and public GraphQL share it; the REST facade delegates to the same contexts.
- The React/LiveView boundary is explicit and permanent — LiveView owns CRUD-and-collaboration surfaces; React owns the two canvas-style editors.
- The prospect warehouse sits upstream of the CRM behind a one-way valve — raw records never enter the CRM; engagement promotes, outcomes flow back, and field-level lineage makes provider retention/purge and attribution enforceable.