Screvercommerce
Tenancy

Many destinations. One platform.

Each destination, operator or region is a tenant with isolated data, configuration and integrations. The platform runs as a single shared application, with row-level tenant scoping and per-tenant configuration.

Properties

Tenancy properties enforced at the access layer.

  • Row-level tenant scoping

    Enforced in Payload (headless) access control on every collection.

  • Per-tenant branding

    Theme tokens, fonts, logos, hero imagery for both seasons.

  • Per-tenant integration credentials

    Connector configurations stored encrypted at rest.

  • Per-tenant content, products, fares, schedules, customers

    Isolated by row-level tenant_id.

  • Per-tenant Stripe account or Stripe Connect routing

    For split payments to providers.

  • Per-tenant data residency option

    EU default; tenant-specific region available.

  • Per-tenant subdomain or custom domain

    With automatic TLS via Cloudflare.

  • Per-tenant locales

    de, fr, en, it, rm and any additional configured.

  • Per-tenant identity provider

    SwissID, SwissPass, OAuth/OIDC, SAML.

  • Per-tenant audit log

    Retention configurable per regulatory regime.

Isolation

Tenant switcher.

Switch between any workspace you have access to. Role and region shown inline; isolation is enforced at the data layer.

app.screver.ch/platform/multi-tenancy
PlatformMulti-tenancyslug: multi-tenancy
MK

Workspaces

Switch workspace

Search workspaces…
Workspace switcher · per-tenant role + region
Resolution

How a request finds its tenant.

Tenancy is a first-class column on every collection. All Payload (headless) access control hooks enforce it. The middleware resolves tenant from subdomain, custom domain, or auth context.

middleware (pseudocode)

function resolveTenant(req) {
  // 1. Subdomain match (mob.screver.app)
  const sub = req.host.split('.')[0];
  if (TENANTS_BY_SUBDOMAIN[sub]) return TENANTS_BY_SUBDOMAIN[sub];

  // 2. Custom domain match (book.glacierexpress.ch)
  if (TENANTS_BY_DOMAIN[req.host]) return TENANTS_BY_DOMAIN[req.host];

  // 3. Auth context (Bearer pk_tenant_xxx)
  const claims = decodeApiKey(req.headers.authorization);
  return claims?.tenant ?? throwUnauthorized();
}

Keep reading