> Every UQL docs page, as Markdown: https://uql-orm.dev/llms.txt
> The same docs over MCP: https://uql-orm.dev/mcp
> Before writing UQL code, read the skill: https://uql-orm.dev/.well-known/agent-skills/uql-orm/SKILL.md

# FAQ

> Short answers to common questions about UQL, from setup to troubleshooting.

Source: https://uql-orm.dev/faq

## Getting started

### What is UQL, and why would I pick it?

UQL is a TypeScript ORM whose queries are plain, typed JSON objects instead of method chains. Your classes are the schema, with no codegen or build step. One query runs on PostgreSQL, CockroachDB, MySQL, MariaDB, SQL Server, the SQLite family (libSQL, Turso, D1) and MongoDB, and travels over HTTP to the browser unchanged.

It ships [vector search](https://uql-orm.dev/ai-semantic-search.md), [multi-tenant filters](https://uql-orm.dev/multi-tenancy.md), [soft delete](https://uql-orm.dev/entities/soft-delete.md), [migrations](https://uql-orm.dev/migrations.md), a [REST API](https://uql-orm.dev/http.md) and a [browser client](https://uql-orm.dev/browser.md) in one package, and adds the least measured time and memory over the driver in our [PostgreSQL benchmark](https://uql-orm.dev/benchmark.md). The [comparison page](https://uql-orm.dev/comparison.md) sets it beside Drizzle, MikroORM, Prisma and TypeORM.

### Where does the name come from?

Unified Query Language: one typed JSON syntax, modeled on MongoDB’s, for SQL databases and MongoDB alike. It is the [first of five things a perfect ORM should have](https://uql-orm.dev/blog/in-search-of-the-perfect-orm.md).

### Is it production-ready?

Yes. It runs in production behind [Variability.ai](https://variability.ai), an AI meeting notetaker by UQL’s author.

## Setup

### Which driver do I install?

Your database’s own: `pg`, `mysql2`, `mariadb`, `better-sqlite3`, `mssql`, `mongodb`, and so on. [Which pool](https://uql-orm.dev/pool.md#which-pool) pairs each entry point with its driver. On Bun, `bun:sql` (PostgreSQL, CockroachDB, MySQL, MariaDB) and `bun:sqlite` need none, and D1 takes the Worker’s binding.

### Do I need special TypeScript settings?

No decorator flags or polyfills: UQL uses [standard TC39 decorators](https://uql-orm.dev/entities/basic.md). `module`, `target` and `lib` matter, as [Requirements](https://uql-orm.dev/getting-started.md#requirements) explains.

### Can I use UQL from JavaScript?

Yes, with [`defineEntity`](https://uql-orm.dev/entities/imperative.md), which registers the same metadata as decorators. The CLI reads a `uql.config.js` like a `.ts` one. Decorators in a `.js` file need Bun or a transpiler such as Babel, SWC or esbuild.

## Queries

### What does “JSON-native” mean?

A query is a plain object, so you can `JSON.stringify()` it, send it over HTTP, cache it, or share it between backend and frontend:

```ts
import type { Query } from 'uql-orm';
import { User } from './shared/models/index.js';

const query: Query<User> = {
  $select: { id: true, name: true },
  $where: { email: { $endsWith: '@uql-orm.dev' } },
  $sort: { createdAt: 'desc' },
  $limit: 10,
};
```

The [HTTP transport](https://uql-orm.dev/http.md) serves your entities as a REST API, and [`HttpQuerier`](https://uql-orm.dev/browser.md) sends these queries to it from the browser.

### What is the difference between `$select` and `$populate`?

`$select` picks scalar fields. `$populate` loads relations, in the same statement:

```ts
const query: Query<User> = {
  $select: { id: true, name: true },
  $populate: { posts: { $select: { title: true } } },
};
```

### How do I filter on a relation or a JSON property?

A relation filters by its fields, and a JSON column by dot-paths. Both work on every SQL dialect:

```ts
await pool.findMany(Post, { $where: { author: { name: 'Roger' } } });
await pool.findMany(Company, { $where: { 'settings.theme': 'dark' } });
```

`$size` filters by how many related rows exist, as a `COUNT(*)` subquery that never loads them:

```ts
await pool.findMany(MeasureUnitCategory, {
  $where: { measureUnits: { $size: { $gte: 2 } } },
});
```

### What is the difference between `type` and `columnType`?

`type` is the portable type the compiler checks the property against, and every field states one, except a foreign key, which takes `references` and inherits the target key’s type, and a relation aggregate, which its aggregate types. `columnType` overrides the SQL type it maps to. See [Column types](https://uql-orm.dev/entities/basic.md#column-types).

### Is UQL safe from SQL injection?

Yes. Every value is bound as a parameter, and table and column names come from entity metadata, never the query.

[`sql`](https://uql-orm.dev/querying/raw-sql.md) is the deliberate opt-out. As a tagged template it binds every interpolated value, and columns come from `refs`:

```ts
import { sql, refs } from 'uql-orm';

const item = refs(Item);
sql`${item.stock} - ${quantity}`;
```

Its callback form does not bind, so never build one from user input. Bind values there with `ctx.addValue()`.

UQL does not use server-side prepared statements, so transaction-mode poolers such as [Supabase’s](https://uql-orm.dev/supabase.md) work without extra configuration.

## Schema and migrations

### Do I write migrations by hand?

No. Edit the entity, run `npx uql-migrate generate:entities <name>` to write a migration from the diff, and `up` to apply it. For your own SQL, `generate <name>` creates an empty migration. See [Migrations](https://uql-orm.dev/migrations.md).

### Can UQL create the database from my entities?

Yes, with `sync`:

```bash
npx uql-migrate sync --dry-run  # print the DDL
npx uql-migrate sync            # create missing tables, columns and indexes
```

By default `sync` only adds: it drops no column and changes no type unless you pass `--unsafe`. Use it on prototypes and test databases, and [generated migrations](https://uql-orm.dev/migrations.md#from-entities-to-the-database) once the data matters. `generate:from-db` goes the other way, from tables to entities.

### Should I use a lifecycle hook or a trigger?

A [lifecycle hook](https://uql-orm.dev/entities/lifecycle-hooks.md) runs in your app on UQL’s own writes, and can call a queue or another service. A [trigger](https://uql-orm.dev/entities/triggers.md) runs in the database, so it also fires on raw SQL, data migrations and other services’ writes. Use a trigger for data every write must produce, such as audit rows, and a hook for application logic. Triggers are SQL-only: on MongoDB, a write to an entity that declares one is refused.

### How do soft delete and multi-tenancy work?

Mark a field `@Field({ softDelete: true })`. Deletes then set it, reads hide those rows, `restoreOneById` and `restoreMany` bring them back, and `{ hardDelete: true }` removes them for good.

Soft delete is one [query filter](https://uql-orm.dev/querying/filters.md), a named `$where` that applies by default. A `security` filter resolved from a per-request context gives you [multi-tenancy](https://uql-orm.dev/multi-tenancy.md): it covers every query, relations and cascades included, a client cannot bypass it, and it fails closed without a context.

### How does vector search work?

Declare `@Field({ type: 'vector', dimensions })` and sort with `$vector`. It runs on PostgreSQL and PGlite (pgvector), CockroachDB, MariaDB, SQLite (sqlite-vec), libSQL/Turso, SQL Server 2025 and MongoDB Atlas. Start with [AI & RAG](https://uql-orm.dev/ai-semantic-search.md); [Semantic Search](https://uql-orm.dev/querying/semantic-search.md) is the reference.

## Troubleshooting

### My decorators do not work

- `target` must not be `esnext` ([Requirements](https://uql-orm.dev/getting-started.md#requirements)).
- A bundler that compiles TypeScript itself must support standard decorators. esbuild, SWC, Babel (`version: '2023-11'`) and Bun do. Oxc, Vite 8’s own transformer, does not: add a plugin for one of the others.
- Next.js compiles legacy decorators only, so it needs [a Babel config](https://uql-orm.dev/nextjs.md#decorators).
- On Node, `uql-migrate` needs `tsx` to import a TypeScript config ([Running the CLI](https://uql-orm.dev/migrations.md#running-the-cli)).

### “Cannot find module ‘uql-orm’”

Set `"module": "nodenext"`, or `"preserve"` behind a bundler, so TypeScript reads the package’s `exports`. If Node runs the output, set `"type": "module"` in `package.json`. Under `nodenext`, relative imports end in `.js`.

### “Cannot find global type ‘AsyncDisposable’”

Add `"lib": ["esnext"]`. `await using` needs it, and no dated target’s default lib has it.

### “Connection refused”

Check that the database is running and exists (`createdb your_db`), the credentials in `uql.config.ts`, and on Docker, the network and port mappings.

### A query is slow

Index the columns you filter by, page with `$limit` and `$skip`, and use [`findManyStream`](https://uql-orm.dev/querying/streaming.md) for large reads. [Query logging](https://uql-orm.dev/logging.md) shows the SQL and its timing.
