Review · VerifiedUpdated 2026-05-03Verified against code 2026-05-03
Verified 2026-05-03 against MEMORY.md (backend branch state, scheduler timings, deployment model) and CLAUDE.md.
Architecture Overview
The 30,000-foot view. Every stage of the loop runs in one of the services below.
Services
| Service | Tech | Hosts | Responsible for (loop stage) |
|---|---|---|---|
nudg3-backend | FastAPI 0.116, Python 3.12 | GCP Cloud Run (EU) | Auth, REST API, multi-tenancy, billing, scheduler triggers, scoring (3) |
nudg3-workflows | LangGraph Platform (Cloud) | LangGraph Cloud (EU) | Collection (1), extraction (2), report generation (4), agent runtime |
nudg3-core | Python package | (shared) | DB models, schemas, session management — used by both backend + workflows |
nudg3-frontend | Next.js 15.4, React 19 | Vercel | Customer dashboard at app.nudg3.ai |
nudg3-frontend-admin | Next.js 15 | Vercel | Internal admin at admin.nudg3.ai |
nudg3-landing | Next.js 15 | Vercel | Marketing at nudg3.ai |
nudg3-mcp-server | FastMCP, Python | GCP Cloud Run | MCP server for programmatic AI access |
Frontend monorepo nudg3-frontend-combined (Turborepo) is the active development surface for all 3 frontends — production repos receive promoted builds.
Data flow at the system level
┌──────────────────────────────────────────┐
│ Cloud Scheduler (EU) │
└─────────────────┬────────────────────────┘
▼ daily 00:30 UTC
┌───────────────────────────────────────────┐
│ nudg3-backend ──────► nudg3-workflows │
│ (FastAPI) (LangGraph) │
│ │ │ │
│ ▼ ▼ │
│ PostgreSQL Cloro async API │
│ (Cloud SQL EU) (provider queries) │
└────────────┬───────────────┬──────────────┘
▼ ▼
webhook callbacks ──► extraction ──► scoring
│
▼
Customer dashboard (Vercel)
Admin dashboard (Vercel)
Public API + MCP server (Cloud Run)Where each loop stage runs
| Loop stage | Service(s) | Notes |
|---|---|---|
| 1 — Collections & Prompts | nudg3-backend (scheduler trigger, prompt × provider matrix), nudg3-workflows (Cloro orchestration), Cloro (external) | Prod env: CLORO_CONCURRENCY_LIMIT=25 |
| 2 — Mentions & Citations | nudg3-workflows (extraction graph) | v1.12 in prod since 2026-04-23 |
| 3 — Aggregated Stats | nudg3-backend (scoring service, deterministic) | Active-prompt filter enforced at fetch_responses_node |
| 4 — Reports & Boosters | nudg3-workflows (visibility analysis graph) | Default model: Claude Sonnet 4.6 |
| 5 — Actions & Content | nudg3-backend (actions API), nudg3-workflows (content gen subgraphs) | URL monitoring registers back into Stage 1 |
| 6 — Historical Tracking | nudg3-backend (delta calc), nudg3-workflows (change-guard logic in report gen) | v3.8.2 rotation gate |
Deployment
- Backend: manual via
scripts/prod-eu/deploy-backend-eu-v2.sh(NOT auto-deploy — see MEMORY) - Workflows:
git push origin main:production-eu(auto-build on LangGraph Cloud) - Frontends: push main → Vercel auto-deploys
- MCP server: Cloud Run, Cloudflare-fronted at
api.nudg3.ai
Key infrastructure invariants
- Multi-tenant: every query filters by
workspace_id. Validation at the API boundary viavalidate_workspace_access(workspace_id, user, db). - Datetime: all timestamps are naive UTC (
datetime.now(timezone.utc).replace(tzinfo=None)). - Active-prompt filter:
is_active=Trueenforced atfetch_responses_nodeonly; downstream nodes inherit via cascade. PR #318 / v3.8.1. - Connection pooling: backend 5/container (max 25), workflows 15/container, system total ~40 of 100 PG limit.
See also
- The Loop — what each service actually does, in product terms
nudg3-backend/CLAUDE.md— backend-specific architecturenudg3-workflows/README.md— workflow architecturedocs/Nudg3_Overview/CONNECTION_POOLING_AND_SESSION_MANAGEMENT.md— pool sizing reference