0) Problem Restatement
Salesforce asked: design a platform that connects a product to many third-party vendors: email providers (Gmail, Outlook), team messaging (Slack, Teams), CRMs, and so on. A customer authorizes their vendor account (OAuth). The product can then invoke vendor actions ("send this message to channel X", "create a contact") and receive vendor events ("a new email arrived") via webhooks. The goal: add new vendors quickly, and make integrations secure and reliable.
1) Architecture
Architecture Diagram
flowchart LR
P["Product services"] -->|"action request"| IAPI["Integration API"]
IAPI --> Q[("Action queue - per vendor")]
Q --> EX["Executors - rate limited per vendor/tenant"]
EX --> CONN["Connector plugins - Slack, Gmail, CRM..."]
CONN --> V["Vendor APIs"]
V -->|"webhooks"| WH["Webhook receiver - verify signatures"]
WH --> EQ[("Event queue")]
EQ --> P
AUTH["OAuth service"] --> VAULT[("Token vault - encrypted")]
CONN --> VAULT2) Key Components
- Connector interface (plugin model): each vendor implements the same small interface:
authorize_url(), exchange_code(), refresh_token()
actions: { "send_message": handler, "create_contact": handler, ... }
parse_webhook(request) -> normalized events
rate_limits(), error_mapping()
Adding a vendor = a new plugin plus config, and the core platform doesn't change.
- OAuth connection: the customer clicks "Connect Slack" → vendor consent screen → callback with a code → exchange it for tokens → store them encrypted in a vault, scoped to (tenant, connection). Request minimum scopes.
- Token refresh: refresh before expiry (background) or on a 401, with a lock so only one refresh happens at a time. Revoked tokens → mark the connection "needs reauthorization" and notify the admin.
3) Reliable Actions
- Actions are async jobs: the product submits
{connection_id, action, params, idempotency_key}and gets a job ID (or waits briefly for fast actions). - Per-vendor and per-tenant rate limiting (token buckets) matches each vendor's limits, e.g., Slack's per-method limits. Queue excess work instead of failing.
- Retries with exponential backoff on 429/5xx, respecting
Retry-After. Don't retry non-retryable errors (400, 403), and surface them clearly. - Idempotency: pass keys to vendors that support them. For others, record completed action keys to avoid duplicates on our own retries.
- Circuit breaker per vendor: during a vendor outage, pause and queue work, and show status.
4) Webhooks (vendor → us)
- A public endpoint per vendor: verify signatures (HMAC with the vendor's secret) and timestamps (to stop replays), and respond fast (200 within the vendor's timeout).
- Put events on a queue, deduplicate by vendor event ID, normalize them into our event format, and route to the right tenant and connection.
- Some vendors need subscription renewal (e.g., Microsoft Graph subscriptions expire), so a scheduler renews them.
5) Operations
- Per-vendor dashboards: success and error rates, latency, rate-limit hits, token refresh failures.
- Fairness: one tenant's bulk sync can't eat all of a vendor's shared app quota (per-tenant limits within the vendor limit).
- Vendor API versioning: connectors pin versions, and contract tests catch breaking changes.
6) Wrap-Up
Give every vendor a connector plugin behind one interface (auth, actions, webhook parsing, limits), connect customer accounts via OAuth with minimum scopes, and keep tokens encrypted in a vault with safe single-flight refresh. Run actions as queued, idempotent jobs with per-vendor and per-tenant rate limits, retries and circuit breakers, and receive vendor events through signature-verified, deduplicated webhooks, with vendor health visible in per-vendor dashboards.