Designing Multi-Tenant Integrations for Your SaaS
If you sell integrations to many customers, you need more than a few webhooks. This post covers patterns for mapping tenants, environments, and credentials to an integration layer.
If your product offers “integrations” as a feature, you’re really running a multi-tenant integration platform—even if you don’t call it that yet.
That means answering questions like:
- How do we isolate credentials per customer?
- How do we let customers configure their own CRMs / webhooks?
- How do we support sandbox vs production?
- How do we reason about limits (events, connections, rules) per tenant?
This post walks through some practical patterns using the idea of workspaces as the core isolation unit.
Workspaces as the integration boundary
A workspace is a container for:
- connections (OAuth + API keys)
- rules (routing & fan-out)
- events + audit history
- usage limits (events, rules, etc.)
Most teams map workspaces to one of three things:
- Customer –
workspace = tenant - Customer + Environment –
workspace = tenant + env - Internal environment –
workspace = app + env
Pattern 1: One workspace per customer
Best when:
- You’re reselling integrations to customers.
- Each customer can connect their own tools (HubSpot, Salesforce, Mailchimp, etc.).
- You want clean isolation of credentials and rules.
Mapping might look like:
// Your tenant model
type Tenant = {
id: string; // "cust_123"
slug: string; // "acme-co"
workspaceId: string; // "ws_01..."
};
Each customer gets:
- their own workspace
- their own connections
- their own rules
Benefits:
- Simple mental model: “Open ACME’s workspace.”
- Easy to attribute usage per customer.
- No credential sharing or risk of cross-tenant leaks.
Pattern 2: One workspace per customer per environment
Best when:
- You support sandbox vs production integrations.
- Customers want to test mapping/routing before going live.
Mapping:
cust_123 + sandbox → ws_cust123_sandboxcust_123 + prod → ws_cust123_prod
Pros:
- Clear separation of test vs live traffic.
- You can apply different limits for sandbox (lower) vs prod (higher).
- You can safely experiment in sandbox without touching real data.
Pattern 3: Internal-only workspaces
If customers never configure integrations directly and you just need a hub between your own systems:
- Use a few shared workspaces:
internal-devinternal-staginginternal-prod
- Put tenant IDs into event resource data, not separate workspaces.
{
"workspace": "ws_internal_prod",
"event": "invoice.paid",
"resource": "billing-core",
"resource_id": "cust_123",
"payload": {
"invoiceId": "inv_123",
"amount": 19900
}
}
Rules and mapping can branch based on resource and resource_id if needed.
Credential isolation per tenant
Multi-tenant integrations mean credentials per tenant:
- ACME connects their HubSpot.
- Contoso connects a different HubSpot account.
- Startups might use MailChimp instead.
- shared tokens
- shared webhooks
- shared rate limits
With a workspace-based model:
- each workspace has its own connections
- each connection has its own auth (OAuth, API key, etc.)
- rotation & revocation happen per workspace/connection
If you build this on top of Meshes, you get:
- per-workspace connections (no cross-tenant sharing)
- per-workspace limits (events, rules, connections)
- a clean API: your app just needs
workspaceId for each tenant
Limits and pricing become clearer
Once you have a workspace-per-tenant mapping, usage becomes:
- events per workspace
- connections per workspace
- rules per workspace
That makes it much easier to:
- align your own pricing (e.g. “5 workspaces, 15 connections”)
- build internal guardrails (hard caps vs enterprise soft overages)
- see who is noisy vs who is quiet
Putting it together with Meshes
At a high level, your integration flow becomes:
- On tenant signup, create a workspace for them.
- When they connect a tool, create a connection in that workspace.
- When they enable an integration, create rules in that workspace.
- When your app emits events, include the workspaceId for that tenant.
You keep your core app simple, but give each tenant a robust integration layer with isolation, limits, and observability built-in.
If you’re starting fresh, this is the perfect time to design the multi-tenant story instead of bolting it on later.