Quorum Production Architecture
Quorum · target design · eu-south-1

Quorum in production

From one EC2 with files on disk to a managed AWS stack: Postgres as the single source of truth, S3 for files, the wiki kept in sync within seconds and in order, and answers tuned to who is asking. Everything is defined in CloudFormation; CloudFront comes later.

The system

VPC · PRIVATE SUBNETS · 2 AZ · S3, BEDROCK, SECRETS VIA VPC ENDPOINTS Team in the browser pages · live sessions Cognito users + Wiki M2M client Wiki (Confluence) pages · webhooks · Forge app CloudFront + WAF later stage ALB + ACM HTTPS · WebSocket API Gateway webhooks in · Wiki API Lambda verify signature, enqueue ECS Fargate · quorum-web pages, API, WebSocket, answers ElastiCache Valkey · fan-out, presence ECS · quorum-worker wiki sync · embed · reports SQS FIFO + DLQ one message group per page EventBridge Scheduler reconcile every 15 min S3 documents · versions Bedrock Claude · embeddings Aurora PostgreSQL + pgvector users · skills · sessions · wiki pages · vectors Secrets Manager KMS · rotation later HTTPS · WSS sign in /, /api, /ws pub/sub files answers SQL webhooks · read calls enqueue in order Wiki API /api/v1 · M2M token one transaction: page + chunks + vectors notify fetch page vN · write back (via NAT)
user pathwiki pathlater stage
People come in through the ALB; the wiki comes in through API Gateway, both for webhooks and for reading Quorum data. Every wiki change is verified, queued per page, and applied by the worker to Postgres in a single transaction, which then tells any live session that uses that page.

Wiki → Quorum: async, but not eventual

The webhook returns in milliseconds and the work happens behind a queue, but each page change is applied exactly once, in the order the wiki made it, and Quorum can say for every page whether it is current. A change that goes missing is caught and repaired, never left to drift.

  1. Wiki fires a webhookpage created, updated, moved, deleted, attachment added.
  2. Lambda verifies and queueschecks the signature, writes {page, version} to SQS FIFO with the page as message group and page+version as dedup id. Returns 200.
  3. Worker fetches vNwebhooks are thin, so the worker reads the page body and restrictions from the wiki REST API.
  4. Embedchunks the page and gets vectors from Bedrock.
  5. One transactionpage row, chunks, vectors and permissions, applied only if vN is newer than what is stored. Readers see the old page or the new one, never half.
  6. Live sessions hear about it“The runbook you're discussing changed (v12 → v13)” in every session that uses the page.

What makes it reliable

  • Per-page order: FIFO message groups keep v13 behind v12; different pages run in parallel.
  • Idempotent: the version check makes replays and duplicates harmless.
  • Bounded lag: an alarm when the oldest message is older than 60 s; failures land in the DLQ, which also alarms.
  • Repair: every 15 minutes the worker compares the wiki's last-modified times with Postgres and re-queues anything behind.
  • Read your own writes: when Quorum writes back to the wiki, it stores the new version in the same request, so the echo webhook is a no-op.
  • Visible: a sync status per page (current, catching up, failed) in Admin.

Quorum → Wiki

  • Read API for the wiki: search, session reports, decisions, and document versions under /api/v1, behind API Gateway with throttling.
  • Machine identity: a Cognito app client with client-credentials and scopes like read:reports, used by a small Forge app or macro in the wiki.
  • Write-back: approved document changes go to the wiki with its version number, so a page edited in the meantime is a conflict to resolve, not an overwrite.

Answers that know who is asking

Each person has a profile: team, role, skills with a level (say Kubernetes 5, RF 2), areas they own, and how deep they like answers. People set it themselves; admins can adjust it; Quorum can suggest skills from activity, which the person confirms.

  1. Question + profilewho is asking, in which session.
  2. Permission filteronly chunks from pages this person may read in the wiki.
  3. Hybrid searchpgvector similarity plus Postgres full-text, in one query.
  4. Re-rank with skillsfavour sources in the person's areas; surface owners as people to ask.
  5. Prompt at their levelan expert gets the diff and commands; a newcomer gets context first.
  6. Answer with sourceslinks to the wiki pages and versions it used.

AWS components

ComponentJob in QuorumReplaces in the POC
VPC2 AZs, public and private subnets, NAT for outbound calls, VPC endpoints for S3, SQS, Secrets, ECR and Bedrockdefault VPC
ALB + ACM + Route 53HTTPS and WebSocket entry, a real hostname and certificateEC2 public IP, port 8000
CloudFront + WAFlateredge caching of static files, rate limits, IP rulessecurity group allow-list
Cognitothe existing pool, plus a machine client and scopes for the wikisame pool
ECS Fargate + ECRquorum-web (2+ tasks) and quorum-worker; images built by Bitbucket PipelinesDocker Compose on EC2
Aurora PostgreSQL Serverless v2system of record: users, profiles, skills, sessions, members, messages, documents, reports, wiki pages, audit; pgvector for retrievalJSON files on EBS
S3uploaded files and every version, wiki attachments, exports; versioning, KMS, lifecycle rulesdocs/vN.md on disk
ElastiCache (Valkey)WebSocket fan-out across web tasks, presence, rate limitsin-process fan-out
API Gateway (HTTP API)wiki webhooks in, Wiki API out, throttling, JWT authorizernone
Lambdawebhook signature check and enqueue; also the Cognito password setter you already havenone
SQS FIFO + DLQordered wiki changes per page; report and document jobsdebounce timer in the process
EventBridge Scheduler15-minute reconcile, nightly re-embed and cleanupnone
BedrockClaude for answers, an embeddings model for retrieval; IAM instead of an API keyOpenRouter key (keep as fallback)
Secrets Manager + KMSDB credentials with rotation, wiki API token, webhook secretsame
SESinvitations from your own domain, no 50-a-day limitCognito default email
CloudWatch + X-Raylogs, queue-age and DLQ alarms, traces, token usage per sessiondocker logs
AWS BackupAurora snapshots and S3 backup plansEBS snapshots

Check which Claude and embedding models Bedrock offers in eu-south-1 directly, and which need the EU cross-region inference profile.

CloudFormation stacks

One stack per layer, each exporting what the next one needs, so the app can be redeployed many times a day without touching the network or the data.

networkVPC, subnets, NAT, endpoints
→
dataAurora, S3, Valkey, KMS, Backup
→
authCognito (exists today)
→
appECS, ALB, SQS, API GW, Lambda, alarms
→
edgeCloudFront, WAF

Separate dev and prod accounts (or at least stacks), with the same templates and different parameters.

Decisions to make before building

  • Wiki permissions. Quorum must never answer from a page the person can't open in the wiki. Mirror page restrictions on sync and filter on every search.
  • PSIP and Quorum. Both index the same wiki. Decide whether Quorum reads from PSIP, or the wiki index moves into Quorum's Postgres. Two indexes of one wiki will disagree.
  • Write-back approval. Who approves a document change before it reaches the wiki, and what happens on a version conflict.
  • Cost guardrails. Token budgets per person and per session, with usage on the dashboard.
  • Retention. How long messages, versions and audit records are kept, and how a person's data is deleted.
  • Retrieval quality. A set of real questions with known good sources, re-run whenever the index or prompts change.
  • Initial load. Bulk import of the existing wiki spaces before webhooks take over.

Why Postgres with pgvector rather than a separate vector store: the page, its chunks, its vectors and its permissions change in one transaction. That is what makes the sync consistent instead of eventual.