Convex Backend
The platform uses Convex as its primary storage backend. All services share a single Convex deployment, with table name prefixes to isolate each service's data. Convex provides real-time queries, transactional mutations, and a managed database that requires no manual schema migrations.
Schema
The unified schema is defined in convex/schema.ts at the platform root. Every service's tables are declared in this single file with prefix naming:
convex/schema.ts # All table definitions
convex/yellowpages.ts # Yellow Pages query/mutation functions
convex/passport.ts # Passport query/mutation functions
convex/ledger.ts # Ledger query/mutation functions
convex/pulse.ts # Pulse query/mutation functions
convex/palette.ts # Palette query/mutation functions
convex/stage.ts # Stage query/mutation functions
convex/billing.ts # Billing query/mutation functions
convex/inference.ts # Inference query/mutation functions
convex/compute.ts # Compute query/mutation functions
convex/auth.ts # Gateway auth state (rate limits, revoked tokens, exchange codes)
Table Prefixes
Each service's tables use a consistent prefix to prevent naming collisions within the shared deployment:
| Prefix | Service | Example Tables |
|---|---|---|
yp_ | Yellow Pages | yp_services, yp_systems, yp_owners |
passport_ | Passport | passport_providers, passport_authorizations, passport_tokens, passport_audit |
pulse_ | Pulse | pulse_events |
ledger_ | Ledger | ledger_events, ledger_policies, ledger_classifications, ledger_lineage |
palette_ | Palette | palette_tokens, palette_components, palette_patterns, palette_standards, palette_a11y |
stage_ | Stage | stage_sessions, stage_files, stage_snapshots, stage_renderState, stage_kv, stage_apps |
billing_ | Billing | billing_items, billing_categories, billing_sync_jobs |
inference_ | Inference | inference_providers, inference_models, inference_requests |
git_ | Git | git_providers, git_repositories, git_webhookEvents |
auth_ | Gateway Auth | auth_rate_limits, auth_revoked_tokens, auth_exchange_codes |
compute_ | Compute | compute_modules |
cal_ | Calendly (reference app) | cal_hosts, cal_event_types, cal_bookings |
SID Bridging
Most tables include a sid field (shift ID) indexed with by_sid. This bridges the app-level nanoid(8) identifiers with Convex's internal _id system. The ConvexStore implementations translate between the two transparently:
- Reads: Query by
sidindex, mapsidtoidin the returned object. - Writes: Generate a nanoid, store it in
sid, let Convex assign its own_id.
Stage tables are an exception -- they use Convex _id directly as session IDs without SID bridging.
Per-Service Functions
Each convex/<service>.ts file exports Convex query and mutation functions. These are server-side functions that run inside the Convex runtime:
// convex/yellowpages.ts
import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
export const getService = query({
args: { sid: v.string() },
handler: async (ctx, args) => {
return await ctx.db
.query("yp_services")
.withIndex("by_sid", (q) => q.eq("sid", args.sid))
.unique();
},
});
The platform's ConvexStore implementations call these functions via the Convex HTTP API using convexQuery() and convexMutation() from @shift/platform-core/convex-client.
Deployment Modes
Convex Cloud
For cloud-hosted deployments, set the CONVEX_URL environment variable to your Convex deployment URL:
CONVEX_URL=https://your-deployment-123.convex.cloud
Self-Hosted Convex
The platform supports self-hosted Convex, which is used in the Kubernetes production and staging environments. Set:
CONVEX_SELF_HOSTED_URL=http://127.0.0.1:3210
CONVEX_ADMIN_KEY=<your-admin-key>
The admin key is required for self-hosted deployments to authenticate API requests. In cloud mode, Convex handles authentication through the deployment URL itself.
The platform's production and staging environments run self-hosted Convex as an in-cluster Kubernetes service. The gateway connects to it via the cluster-internal URL.
Deploying Functions
Convex functions must be deployed to the Convex backend before they can be called. Use the Convex CLI:
# Deploy to cloud
npx convex deploy
# Deploy to self-hosted
npx convex deploy --url $CONVEX_SELF_HOSTED_URL --admin-key $CONVEX_ADMIN_KEY
This pushes the schema and all function definitions from the convex/ directory to the deployment. The deployment automatically handles schema changes -- adding new tables, fields, or indexes does not require manual migration steps.
Environment Variables
| Variable | Purpose |
|---|---|
CONVEX_URL | Convex Cloud deployment URL |
CONVEX_SELF_HOSTED_URL | Self-hosted Convex URL (e.g., http://127.0.0.1:3210) |
CONVEX_ADMIN_KEY | Admin key for self-hosted Convex authentication |
SHIFT_STORAGE | Must be convex (or unset) to use this backend |