Skip to content

Platform Architecture

GrowthOS is built around a central event bus that connects every growth module to a shared data layer and analytics backbone. Modules never talk to each other directly — they emit events, and the platform routes those events to the right destinations.

Every event follows a canonical schema, gets persisted to PostgreSQL for operational use, and forwarded to PostHog for analytics, feature flags, and experimentation.


  • Runtime: Node.js or Python
  • Framework: Express or FastAPI
  • Database: PostgreSQL with row-level security for multi-tenancy
  • Event Streaming: Kafka or RedPanda (self-hosted)
  • Workflow Orchestration: Temporal.io for durable, long-running workflows
  • Email Delivery: SES or Postmark

Every component in GrowthOS goes through a deliberate build-or-buy evaluation. The guiding principle: build what creates defensible IP, integrate proven FOSS, buy commodity infrastructure.

ComponentDecisionRationale
Contact graphBuildCore IP — unified identity is the moat
Event busSelf-hostRedPanda (Kafka-compatible, lower ops overhead)
PostgreSQLSelf-hostOperational data store with RLS
Temporal.ioSelf-hostWorkflow orchestration for sequences and campaigns
AnalyticsIntegratePostHog FOSS edition — proven at scale
Feature flagsIntegratePostHog feature flags — already in the stack
Email automationEvaluateMautic or Laudspeaker (FOSS options)
NotificationsEvaluateNovu (open-source notification infra)
WebhooksEvaluaten8n (workflow automation, self-hostable)
Email deliveryBuySES or Postmark — commodity
WhatsAppBuyGupshup or Twilio
SMSBuyTwilio or MessageBird
Referral engineBuildCore growth module — key differentiator
Waitlist / Advocacy / MilestonesBuildCore growth modules
SDK / Web ComponentsBuildDeveloper-facing surface — must own
DashboardBuildTenant and admin experience — must own

Every event in GrowthOS follows a canonical JSON schema. This ensures consistent processing across the event bus, database, and PostHog.

{
"event": "referral.completed",
"contact_id": "c_8f2a3b1d",
"tenant_id": "t_acme_inc",
"properties": {
"referrer_id": "c_4e7c9a0f",
"campaign_id": "camp_launch_2026",
"reward_type": "credit",
"reward_amount": 20
},
"timestamp": "2026-02-23T14:32:00Z",
"source_module": "referrals"
}

GrowthOS is multi-tenant by design. Every row in every table includes a tenant_id, and PostgreSQL row-level security (RLS) policies enforce isolation at the database level.

  • Every query is automatically scoped by tenant_id
  • RLS policies are enforced even if application code has a bug
  • Tenant data is partitioned — no cross-tenant leakage by construction
  • API keys are scoped to a single tenant

Modules never talk to delivery channels (email, SMS, WhatsApp, push) directly. Instead, they call an internal comms.send() API that handles provider selection, rate limiting, and delivery tracking.

This means:

  • Modules are provider-agnostic — swap SES for Postmark without touching module code
  • Rate limiting and retries are centralized, not duplicated per module
  • Delivery analytics flow back through the event bus like any other event