Callout: Lay the foundation early. This kind of platform becomes core infra—treat auth, tenancy, and run-safety (idempotency, retries, rate limits) as first-class from day one. UI can evolve; the execution guarantees are the product.
Learning Goals
- Understand the core building blocks of an integration SaaS (connectors, triggers, actions, workflows, runs).
- Implement multi-tenancy across data, auth, rate limits, and webhooks.
- Ship an MVP slice: Webhook/Poll Trigger → Transformation → Action with safe execution (retries, backoff, idempotency).
- Add observability: per-tenant logs, run traces, and error analytics.
Reference Architecture (Mental Model)
- Control Plane: Tenants, users, workspaces, roles, plans, billing, connector registry, quotas.
- Data Plane: Trigger ingestion (webhooks & polling), job queue, workers, secret vault, action dispatch, run logs.
- UX: Flow builder (nodes/edges), connector catalog, run history, error drill-downs.
- Contracts: Connector SDK (trigger/action schema), events (
RunStarted
,StepSucceeded
,RunFailed
), audit logs.
Core Concepts
- Connector: Package with
manifest.json
+ code; exposes triggers and actions. - Trigger: Webhook or polling source that emits normalized events.
- Action: Side-effect step (e.g., create contact, send email).
- Workflow: Directed graph of steps with mapping/transform nodes.
- Run: A single execution instance with steps, retries, and final status.
- Auth Vault: Per-tenant encrypted secrets storage + token refreshers.
- Idempotency: Keys at trigger intake and action dispatch to prevent duplicates.
- Rate Limiting: Per-tenant, per-connector, and per-endpoint buckets.
- Observability: Structured logs, metrics, traces, replay with redaction.
MVP Scope (Keep it Tiny)
- Tenancy:
tenants
,users
,workspace_members
,api_keys
. - Registry:
connectors
,versions
,triggers
,actions
. - Auth Vault:
credentials
(encrypted), token refresh jobs. - Workflows:
flows
,flow_versions
,flow_runs
,run_steps
. - Execution: webhook intake → queue → worker → action dispatch.
- Observability: run log stream, searchable by tenant/flow/run.
Exercise A — Multi-Tenant Skeleton
Objective: Stand up the core tables and guards.
- Create tables (prefix with
mt_
if you like):tenants(id, slug, plan, created_at)
users(id, email)
workspaces(id, tenant_id, name)
workspace_members(workspace_id, user_id, role)
api_keys(id, workspace_id, token_hash, scopes, created_at)
- Middleware:
- Resolve tenant context by API key or session cookie.
- Enforce row-level scoping: every select/insert requires
tenant_id
orworkspace_id
join.
- Acceptance:
- A user with an API key can CRUD flows only in their workspace.
- Requests without a tenant context fail with a clear error.
Exercise B — Connector SDK (Hello World)
Objective: Define the connector contract and load one connector dynamically.
- Connector Manifest (example):
{ "name": "github", "version": "0.1.0", "auth": { "type": "oauth2", "scopes": ["repo", "user:email"] }, "triggers": [ { "key": "issue_opened", "type": "webhook", "payloadSchema": "IssueEvent" } ], "actions": [ { "key": "create_issue", "inputSchema": "IssueCreateInput" } ] }