Kura
Early Access: Documentation is actively evolving and may change without notice.

Migrations

Generate and apply PostgreSQL migrations from your TypeScript schema.

KuraDB uses a schema-first migration workflow. You define tables in src/schema.ts, generate named SQL migration files, review them, and apply them from either the txAdmin console or the standalone CLI bundled in the release zip.

The same schema definition also drives the generated Lua ORM metadata under kura.db.tables.

Workflow

Define your schema

Edit src/schema.ts to add or modify tables:

export const users = defineTable('public', 'users', {
  id: defineColumn('id', 'uuid', { primaryKey: true }),
  username: defineColumn('username', 'string'),
  createdAt: defineColumn('created_at', 'date', { defaultExpression: 'NOW()' }),
});

Generate migrations

Run from the txAdmin console or from the extracted kuradb release directory:

kuradb generate

Or give the migration a custom name:

kuradb generate add_users_table

If you only want to refresh lib/schema.generated.lua without creating a migration:

kuradb generate --types-only

This updates:

  • migrations/0000_<name>.sql
  • migrations/meta/_journal.json
  • migrations/meta/0000_snapshot.json
  • lib/schema.generated.lua
✓ Generated migration: migrations/0000_init_users.sql
✓ Updated journal: migrations/meta/_journal.json
✓ Generated Lua types: lib/schema.generated.lua
✓ Schema generated: 3 tables ready
Run "kuradb migrate" to apply pending migration files

Review the SQL

Open the generated migration file and inspect it:

-- Auto-generated by kuradb
-- Tag: init_users
-- Generated at: 2026-04-22T12:00:00.000Z

CREATE TABLE IF NOT EXISTS "public"."users" (
  "id" UUID PRIMARY KEY,
  "username" VARCHAR(255) NOT NULL,
  "created_at" TIMESTAMP NOT NULL DEFAULT NOW()
);

Always review

Review generated SQL before applying it, especially in production. You can edit the generated .sql file to add ALTER TABLE statements or adjust anything the generator does not cover.

Apply migrations

kuradb migrate
Applying 3 migration file(s)...
✓ Applied 0000_init_users.sql
✓ Applied 0001_add_posts.sql
✓ Applied 0002_add_comments.sql
✓ Updated Lua types
✓ Migration complete

If a migration fails, remaining migrations are skipped and the error is printed.

For the standalone CLI, set KURADB_CONNECTION_STRING first:

KURADB_CONNECTION_STRING="postgres://user:password@localhost:5432/fivem" kuradb migrate

Generated files

migrations/0000_<name>.sql

Plain SQL for a single migration. Safe to edit before running kuradb migrate.

migrations/meta/_journal.json

Tracks migration order and schema snapshots.

public.__kuradb_migrations

Applied migrations are tracked in PostgreSQL so the state survives resource restarts:

SELECT "id", "tag", "applied_at"
FROM "public"."__kuradb_migrations"
ORDER BY "applied_at" ASC;

lib/schema.generated.lua

This is the generated Lua ORM metadata. It now includes:

  • row / insert / update types
  • generated tables under kura.db.tables
  • string column maps under table.columns
  • richer column refs under table.columnRefs
  • direct aliases such as users.id and users.createdAt when the field name is safe

Excerpt:

---@class UsersColumns
---@field id KuraDBColumnRef<string>
---@field createdAt KuraDBColumnRef<number>

---@class UsersTable : KuraDBTable<UsersRow, UsersInsert, UsersUpdate>
---@field columnRefs UsersColumns
---@field id KuraDBColumnRef<string>
---@field createdAt KuraDBColumnRef<number>

local users = kura.db.tables.users

users.columns.createdAt         -- "created_at"
users.columnRefs.createdAt.sqlName -- "created_at"
users.createdAt                 -- generated column ref

Use the generated metadata for autocomplete:

local users = kura.db.tables.users

local rows = kura.db.select({ users.id, users.createdAt })
  :from(users)
  :await()

print(rows[1].createdAt)

The concrete table names under kura.db.tables come from your own schema.ts. If your schema exports characters and vehicles, those are the generated Lua tables you will see.

Listening for migrations

Other resources can react when migrations are applied:

AddEventHandler('kuradb:schemaMigrated', function(schema)
  print('Schema updated')
end)

Tips

  • Always run kuradb generate before kuradb migrate
  • Use kuradb generate --types-only when you only need fresh Lua types from the schema
  • Review generated SQL before applying it
  • Applied migrations are tracked in public.__kuradb_migrations
  • Lua types and generated table refs are regenerated on both generate and migrate
  • No resource restart is needed between generate and migrate

On this page