The database is the foundation of every feature in Vuesion.
Rather than treating it as an implementation detail, Vuesion starts new features by modeling the domain first. The resulting Prisma schema becomes the source from which the rest of the backend grows.
This approach keeps the application consistent as it evolves and allows generators to build upon a stable foundation.
Vuesion uses PostgreSQL together with Prisma.
PostgreSQL provides a mature, reliable relational database, while Prisma offers a type-safe API for interacting with it.
Together they provide:
Vuesion intentionally stays close to standard Prisma without introducing additional abstraction layers.
Instead of storing every model in a single schema.prisma file, Vuesion organizes the schema by domain.
prisma/
├── schema/
│ ├── auth.prisma
│ ├── config.prisma
│ ├── file.prisma
│ ├── user.prisma
│ └── workspace.prisma
├── migrations/
└── seed.ts
As the application grows, this keeps related models together and makes navigating the schema significantly easier.
Each domain owns the models that belong to it.
One of the core ideas behind Vuesion is that the Prisma schema comes first.
A typical workflow looks like this:
Prisma schema
│
▼
Database migration
│
▼
Generated Prisma Client
│
▼
Backend implementation
│
▼
Application feature
Because generators build upon the Prisma models, defining the data model is usually the first implementation step of a new feature.
Vuesion models relationships explicitly.
Foreign keys are used throughout the schema and database integrity is enforced by PostgreSQL.
Cascade rules are configured where appropriate so related records remain consistent without requiring additional application code.
The database should enforce structural integrity whenever possible.
Vuesion uses ULIDs as primary keys.
Unlike random UUIDs, ULIDs preserve chronological ordering while remaining globally unique.
This improves index locality inside PostgreSQL and results in more balanced B-tree indexes as new records are inserted.
ULIDs also remain URL-friendly and can be generated without requiring a database round trip.
Database changes are managed through Prisma migrations.
Whenever the schema changes, a corresponding migration records the structural changes required by the database.
This ensures that every environment evolves through the same sequence of schema changes.
Migrations should always be committed together with the corresponding schema updates.
The Vuesion repository always contains exactly one migration, init, which creates the complete current schema. New installations start from an empty database and apply it with npm run db:migrate. Schema changes of a Vuesion release are folded into init instead of being added as new migrations.
After you start your own project, the migration history is yours. Keep the prisma/migrations folder of your project and add your own models and fields with your own migrations. Never replace it with the init migration of a newer Vuesion release: an applied migration must never change.
Follow these steps to update an existing installation to a new Vuesion version:
prisma/migrations folder. Do not copy the migrations of the new version.prisma/schema, and merge them if you changed these models.npm run db:migrate
update_vuesion_1_5_0 for version 1.5.0. To pass the name directly, run npx prisma migrate dev --name update_vuesion_1_5_0 and then npm run db:generate-client. npm run db:migrate -- --name <name> does not work, because npm appends the arguments to the end of the script, after npm run db:generate-client.npm run db:seed.npm run db:migrate-deploy.Prisma automatically generates a fully typed database client from the schema.
Services interact directly with this generated client.
No custom repository layer is required.
This keeps database access simple while still maintaining a clear separation between persistence and business logic.
Vuesion includes a seed entry point, prisma/seed.ts, which initializes the data every installation needs:
Feature table.Free plan if no plan exists yet.Both steps are safe to run repeatedly, so the seed runs after the migrations on every deployment:
npm run db:migrate-deploy
npm run db:seed
The seed does not create demo users, sample workspaces, or example content. Every application has different initial data requirements, so teams can extend the seed according to their own project needs. Keep additions idempotent, because the seed also runs against existing databases and seeds the test database.
See Plans & Entitlements for details on features and the initial plan.
Vuesion generally performs permanent deletes.
Records are removed from the database instead of being soft deleted.
The main exception is the file domain.
Files are deleted asynchronously so that associated assets can first be removed from the external object storage before the corresponding database records disappear.
Vuesion does not prescribe a strict rule regarding JSON columns.
Whenever a JSON field provides the best representation of a particular problem, it should be used.
Likewise, relational models should be preferred whenever the data benefits from explicit relationships and querying capabilities.
The choice should be driven by the domain rather than by a general architectural preference.
Many projects treat the database as a storage layer that is designed after the application.
Vuesion takes the opposite approach.
The data model defines the language of the domain and becomes the starting point for the rest of the implementation.
This provides:
The result is a database structure that remains understandable and maintainable as both the application and the team grow.
Continue with Testing to learn how Vuesion verifies every layer of the application through automated tests.