Akash Ramesh Full Stack Software Engineer ← Back to portfolio

Search Sensei: Multi Tenant SaaS Customer PortalLive

Billing and identity architecture for a live, paying client's multi tenant SaaS platform.

ASP.NET Core 8React 18 TypeScriptKeycloak 26 Stripe Checkout + MetersBookStackZammad DockerAzure App Service

What it is

Search Sensei wraps an existing enterprise search API in a multi tenant customer portal. Organisations self register, choose a subscription plan, and get an isolated workspace with authentication, billing, a knowledge base, and support ticketing. There is zero cross tenant visibility between organisations.

Onboarding dropped from manual provisioning to under five minutes once the portal shipped.

Architecture

React SPA Keycloak 26 ASP.NET Core 8 Stripe BookStack Zammad Search API

Browser authenticates via Auth Code + PKCE with Keycloak, then sends Bearer JWT to the backend. The backend is the only component that talks to the outside world. It proxies every downstream call, attaching the right credential per service. The browser never sees the BookStack PAT, the Zammad PAT, or the Stripe secret key.

Decisions

01

Metered billing with idempotent usage reporting

Three consumption dimensions tracked through Stripe: search query volume, document pages indexed, and additional sites crawled. An internal endpoint accepts usage events and requires a caller supplied idempotency key. It forwards each event to Stripe as a meter event only once, preventing double counting on retries. Subscription and customer IDs are stored as attributes on the Keycloak organisation itself, not duplicated into a first party database. This gives a single source of truth for which org maps to which Stripe customer.

02

Keycloak Organisations for multi tenancy

The system uses Keycloak 26 native Organisations to scope users, roles, and sessions to an org boundary, instead of building tenant isolation into application code. The backend resolves the current tenant from an active_tenant claim on every request. Isolation lives in a battle tested layer rather than bespoke logic.

03

Backend proxy pattern for third party credentials

BookStack and Zammad both require long lived Personal Access Tokens. Every call passes through the ASP.NET Core backend. The backend holds the PAT and returns only what the authenticated user is allowed to see. No dedicated API gateway is needed. The backend itself is the trust boundary.

Outcomes

  • Onboarding time: manual provisioning to under 5 minutes, self service
  • Credential exposure surface reduced: BookStack and Zammad PATs never reach the browser
  • Shipped v1.0.0 to a live, paying client

Integration footprint

ServiceRoleAuth method
Keycloak 26Identity, multi tenant org management, SSO brokerClient Secret + PKCE
StripeCheckout, subscriptions, metered billingSecret Key + Webhook Signature
BookStackKnowledge base via backend proxyPAT via backend proxy
ZammadSupport ticketing via backend proxyAPI Token via backend proxy

Screenshots

Screenshots available on request This is a client project. Visual assets are shared during interviews and technical reviews.

Downloads

← Back to home