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_idorworkspace_idjoin.
- 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" } ] }