Skip to main content

Multi-Tenancy

NearSync supports two multi-tenancy models from a single codebase with zero code forking. Managed clients share a NearSync-hosted Supabase instance, isolated by organization ID and Row-Level Security policies. BYOK (Bring Your Own Keys) clients run the same application code against their own Supabase project for full data sovereignty.

Core Principle: One Codebase, Many Clients

Every client runs the exact same application code. There are no forks, no per-client repositories, and no industry-specific templates. The difference between clients is configuration:

+----------------------------------------------------------+
| NearSync Platform (one codebase) |
| apps/admin-dashboard apps/client-portal packages/* |
+--------------+-----------------------+-------------------+
| |
+---------v----------+ +---------v-----------+
| Managed Path | | BYOK Path |
| | | |
| NearSync Supabase | | Client's Supabase |
| (shared, multi- | | (dedicated, client- |
| tenant via org_id)| | owned infra) |
| | | |
| org_id RLS isolates| | Full DB is theirs |
| each client's data | | No seat limits |
+---------------------+ +----------------------+

The application reads a SystemManifest from the database at runtime and gates modules, features, branding, and limits accordingly. See Manifest-Driven Gating for details on how runtime configuration works.

Managed Multi-Tenancy

How It Works

All managed clients share a single Supabase project. Each client is assigned an org_id when their organization is created. Every tenant-scoped table includes an org_id column, and RESTRICTIVE Row-Level Security policies ensure that queries only return rows belonging to the authenticated user's organization.

Client User Logs In
|
v
Supabase Auth
- User created in auth.users table
- JWT issued with user_id claim
|
v
Profile Lookup (profiles table)
WHERE id = <user_id>
-> Resolves org_id, role, name, avatar
|
v
Every Query Scoped by org_id

RLS Policy (RESTRICTIVE):
org_id = (
SELECT org_id FROM profiles
WHERE id = auth.uid()
)

Applied automatically to SELECT, INSERT, UPDATE, DELETE

RLS Enforcement

NearSync uses PostgreSQL RESTRICTIVE policies for tenant isolation. The key properties of this approach:

  • RESTRICTIVE policies are AND-ed with any permissive policies. Even if a permissive SELECT policy grants access, the RESTRICTIVE org_id check still applies.
  • No cross-tenant data leakage is possible at the database level. A user cannot see, update, or delete rows from another organization.
  • Automatic enforcement - Supabase applies RLS to all queries, including those made through the Supabase client libraries and direct SQL.

Every tenant-scoped table carries an org_id column with isolation enforced, spanning all functional domains:

DomainExample Tables
Coreorganizations, profiles, global_settings, audit_logs
CRMcrm_contacts, crm_companies, crm_pipelines, crm_tasks
Financefinance_invoices, finance_company_expenses, finance_payments
HRMShrms_employees, hrms_attendance, hrms_payroll
Supportsupport_tickets, support_attachments, support_comments
Commschat_messages, email_logs, whatsapp_messages
Projectsprojects, project_tasks, project_sprints, project_documents
Workflowsworkflow_definitions, workflow_executions, workflow_approval_requests
Bookingsbookings, booking_links, booking_time_slots
Assetsassets, asset_allocations, asset_maintenance
Knowledge Basekb_articles, kb_categories, kb_ratings
Custom Fieldscustom_field_definitions, crm_contact_custom_fields
Marketingmarketing_campaigns, marketing_email_sequences
Integrationsintegration_configs, webhook_endpoints, oauth_states

Managed Provisioning

When a new managed client signs up:

  1. Auth trigger creates an organizations row with a new org_id
  2. A SystemManifest is seeded based on the selected tier
  3. An admin profile is created with the super_admin role
  4. Default RBAC roles and permissions are seeded
  5. The user is redirected to the admin dashboard with all gated modules visible

No Vercel projects to create. No repositories to fork. No DNS to configure. The client uses the same deployment as every other managed client, isolated by their org_id.

Tier upgrades are handled by updating the SystemManifest in the database. Module access and feature flags change in real time with no infrastructure changes and no redeployment.

BYOK (Bring Your Own Keys)

How It Works

BYOK clients deploy the same application code but point to their own Supabase project via environment variables. The client owns their entire database, including encryption keys, backups, and region selection.

Key differences from managed:

AspectManagedBYOK
DatabaseShared Supabase instanceClient's own Supabase project
Isolation mechanismorg_id + RESTRICTIVE RLSSingle-tenant; entire DB belongs to client
SeatsEnforced via SystemManifest max_usersNo seat limit; client owns infrastructure
Data sovereigntyNearSync manages infrastructureClient owns all data, encryption keys, backups
RLS roleEnforces org-level isolationEnforces role-based access (admin vs. user)
MonitoringDirect metadata queries on shared DBSentinel heartbeat via Edge Function (metadata only, no PII)

BYOK Provisioning

During the onboarding process:

  1. Client creates their own Supabase project (in any supported region)
  2. Client provides connection credentials via the Setup tab in the client portal
  3. NearSync validates the connection
  4. The full schema (all tables with migrations) is applied to the client's database
  5. A SystemManifest is seeded with the client's tier configuration and region defaults
  6. An admin user and RBAC hierarchy are created
  7. A Sentinel heartbeat Edge Function is deployed for monitoring

BYOK Deployment Options

NearSync-managed hosting (default): A separate Vercel project is created pointing to the same codebase repository, configured with the client's Supabase environment variables. When NearSync pushes to main, the client's project auto-rebuilds alongside all others. Every client receives updates simultaneously.

Client self-hosted (enterprise): NearSync provides static build artifacts and deployment guides per release. The client deploys to their own Vercel, Netlify, Cloudflare Pages, or Docker infrastructure. Database migration diffs are provided with each release for the client to apply.

BYOK Key Handling

Security is a first-class concern in the BYOK flow:

  1. The client's service_role_key is used once during provisioning to apply schema and seed defaults
  2. After provisioning completes, the key is discarded. It is never stored on NearSync infrastructure and never logged.
  3. The client retains sole custody of their service role key going forward
  4. The application code only uses the anon_key (read-only, RLS-enforced) at runtime

Software Update Propagation

Deployment PathHow Updates Flow
ManagedAutomatic. Push to main triggers Vercel rebuild. All managed clients share the same deployment.
BYOK (NearSync-hosted)Automatic. Same mechanism as managed. Push to main rebuilds the client's Vercel project too.
BYOK (Self-hosted)Manual. Client pulls latest build artifacts from the release. NearSync provides migration SQL diffs per release.

Sentinel Monitoring

NearSync's monitoring system (Sentinel) works differently for each deployment model:

Managed clients: NearSync queries metadata-only views on the shared database. These views expose aggregate statistics (active user count, recent activity counts, tier information) without accessing any PII.

BYOK clients: A Sentinel Edge Function deployed to the client's Supabase responds to authenticated heartbeat requests from NearSync. The heartbeat returns only metadata: active user count, tier, application version, and a timestamp. NearSync polls hourly. No PII is transmitted.

The Sentinel heartbeat is authenticated via signed JWT. Unauthenticated requests are rejected.

Region Defaults

When provisioning a new client, operational defaults are applied based on the client's region:

RegionTimezoneCurrencyDate FormatDefault Work Days
AEAsia/DubaiAEDDD/MM/YYYYMon-Fri
USAmerica/New_YorkUSDMM/DD/YYYYMon-Fri
EUEurope/LondonEURDD/MM/YYYYMon-Fri
INAsia/KolkataINRDD/MM/YYYYMon-Sat
SAAsia/RiyadhSARDD/MM/YYYYSun-Thu

These defaults are written into the SystemManifest at provisioning time and can be customized by the client afterward.

Custom Fields Engine

Instead of maintaining per-industry code forks, NearSync uses a custom fields engine to support vertical-specific requirements.

Each organization can define custom fields on any entity type (contacts, companies, deals, invoices, employees, expenses, and more). Field definitions include type (text, number, select, multi-select, date, boolean, URL, email, phone, currency), validation rules, and whether the field is required.

Field values are stored in entity-specific tables and rendered dynamically by a CustomFieldInput component that reads the definitions from the manifest.

This means a healthcare client can add fields like "medical license number" and "insurance provider" while a retail client adds "product SKU" and "inventory location", all using the same application code.