Database Overview

Prisma v7 + PostgreSQL β€” the data layer powering every Nebutra application.

Nebutra uses Prisma v7 as the ORM and PostgreSQL as the database engine. The stack is designed for multi-tenant SaaS: shared schemas, row-level security, pgvector for AI embeddings, and provider flexibility (Neon or Supabase).

Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚          Application Code           β”‚
β”‚  (Next.js Server Components, API)   β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚ import { db } from "@nebutra/db"
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           Prisma v7 Client          β”‚
β”‚     (type-safe query builder)       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚ PostgreSQL wire protocol
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚       Connection Pooler             β”‚
β”‚  PgBouncer (Neon) / Supavisor       β”‚
β”‚  (Supabase) β€” prevents conn. exhaustβ”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚         PostgreSQL Database         β”‚
β”‚  pgvector Β· RLS Β· multi-schema      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

All application code imports the pre-configured db singleton from @nebutra/db. Direct Prisma imports are not used in application code.

Schema layout

The Prisma schema is split across four PostgreSQL schemas, each representing a product domain:

PostgreSQL schemaPurposeKey models
publicCore SaaS platformOrganization, User, Subscription, AuditLog, ApiKey
ecommerceE-commerce featuresProduct, Order, Cart, Payment, Fulfillment
recsysRecommendation systemEmbedding, Interaction, Recommendation, FeatureVector
web3Blockchain / wallet featuresWallet, Token, Transaction, SmartContract

The full schema lives at packages/platform/db/prisma/schema.prisma (~1,400 lines).

Key models

ModelSchemaDescription
OrganizationpublicA tenant β€” the top-level billing and access boundary
UserpublicAn authenticated identity; belongs to one or more organizations
SubscriptionpublicStripe subscription attached to an organization
AuditLogpublicImmutable event log for compliance and debugging
ApiKeypublicScoped API credentials issued per organization
ContentpublicCMS content items (pages, posts, blocks)
IntegrationpublicThird-party integration configs per organization
ProjectpublicA workspace inside an organization

pgvector

PostgreSQL's pgvector extension is enabled on every Nebutra database. It powers:

  • Semantic search β€” cosine similarity over Embedding vectors in the recsys schema
  • RAG pipelines β€” chunked document embeddings stored alongside content
  • Recommendation engine β€” collaborative filtering via ANN (approximate nearest-neighbour) queries

pgvector must be enabled on your PostgreSQL instance before running migrations. Both Neon and Supabase enable it by default. Self-hosted PostgreSQL requires CREATE EXTENSION vector;.

Command reference

CommandWhen to use
pnpm db:generateAfter editing schema.prisma β€” regenerates the Prisma client
pnpm db:migrateCreate and apply a new migration (development and CI/CD)
pnpm db:pushPush schema changes without a migration file (local prototyping only)
pnpm db:studioOpen Prisma Studio at http://localhost:5555
pnpm db:seedPopulate the database with development seed data

Never run pnpm db:push against a production or staging database. It applies schema changes without a migration history, which can cause irreversible data loss.

Multi-tenancy

Every table in the public schema that stores tenant-specific data has a tenantId column. Queries are automatically scoped using PostgreSQL Row-Level Security (RLS) via the withRls helper from @nebutra/tenant. See the RLS guide for details.

How is this guide?

Edit on GitHub

Last updated on

On this page