← ALL LOGS

A multi-tenant adapter layer that doesn't rot into spaghetti

Integration code rots in a predictable way: the first client is clean, the fifth has three if (tenant === ...) branches, the tenth is unmaintainable. The fix is structural — make “a new integration” mean “a new adapter,” never “a new branch in the core.”

One contract, enforced

Every external system implements the same interface. The router never knows which CRM it’s talking to.

interface Adapter {
  id: string;
  send(event: NormalizedEvent, ctx: TenantContext): Promise<Result>;
  verify(req: IncomingRequest): boolean;
}

Push the mess to the edges

Tenant-specific quirks live inside an adapter, behind that contract — never in the router, the queue, or the store. The core pipeline stays generic: normalize, dedup, route. When onboarding is “write one file that satisfies Adapter,” the codebase stops fighting you at client number ten.