Overview#
AlloyDB Omni
is the downloadable edition of Google's AlloyDB for PostgreSQL — the same
engine, shipped as a container image (google/alloydbomni), an RPM, or a
Kubernetes operator, and run on hardware you control. Clients connect with the
ordinary pg driver on 5432, so AlloyDBOmniDialect extends
AlloyDBDialect and inherits its columnar-engine,
model-integration (google_ml_integration) and ScaNN builders unchanged.| Property | Value |
|---|
| Dialect name | alloydbomni |
| Extends | AlloyDBDialect |
| Driver | pg |
| Default port | 5432 |
| Cloud SDK | none |
| Local runtime | the google/alloydbomni image |
Quick start#
Install#
$ npm install ts-prorm-orm pg
$ pnpm add ts-prorm-orm pg
$ yarn add ts-prorm-orm pg
$ bun add ts-prorm-orm pg
pg is the same driver the alloydb dialect uses. pg-copy-streams is optional: only the features that need it load it.Connect#
import { Prorm } from 'ts-prorm-orm';
export const db = new Prorm({
dialect: 'alloydbomni',
host: 'localhost',
database: 'postgres',
username: 'postgres',
password: process.env.OMNI_PASSWORD,
});
import { Prorm } from 'ts-prorm-orm';
export const db = new Prorm({
dialect: 'alloydbomni',
url: 'alloydbomni://postgres:secret@localhost:5432/postgres',
});
A URL is folded into host, port, database, username and password before the dialect is built; any of those passed alongside it wins.Define a model#
import { DataTypes } from 'ts-prorm-orm';
const User = db.define('User', {
id: { type: DataTypes.INTEGER(), primaryKey: true, autoIncrement: true },
email: { type: DataTypes.STRING(255), allowNull: false, unique: true },
name: { type: DataTypes.STRING(100) },
meta: { type: DataTypes.JSONB() },
});
await db.sync(); // CREATE TABLE — see Generated SQL below
meta is JSONB, which the containment query below needs.Query#
import { Op } from 'ts-prorm-orm';
await User.create({ email: 'ada@example.com', name: 'Ada' });
const page = await User.findAll({
where: { name: { [Op.like]: 'A%' } },
order: [['id', 'ASC']],
limit: 20,
offset: 40,
});
Managed and cloud variants#
Password login only: the Quick start above is the whole story.[!CAUTION] Google IAM (iam) is refused
AlloyDB Omni does not support Google IAM database authentication: there is no Google control plane to issue alloydb.login tokens for a server you run. Connect with a PostgreSQL password (or Active Directory / Kerberos configured in pg_hba), and use the alloydb dialect for managed AlloyDB with IAM. The dialect throws at construction.
Generated SQL#
Each block is the statement the model call above it hands the dialect's query(), captured with the driver stubbed out. The model layer inlines the values.Create table#
db.sync() for the model in the Quick start:CREATE TABLE
Insert, update and delete#
await User.create({ email: 'ada@example.com', name: 'Ada' });
await User.update({ name: 'Grace' }, { where: { email: 'ada@example.com' } });
await User.destroy({ where: { id: 1 } });
Upsert#
await User.upsert({ id: 1, email: 'ada@example.com', name: 'Ada Lovelace' });
upsert() also reads the row by primary key before and after the write, to return the instance.await User.findAll({
where: { name: { [Op.like]: 'A%' } },
order: [['id', 'ASC']],
limit: 20,
offset: 40,
});
JSON#
Containment on the meta column:import { Op } from 'ts-prorm-orm';
await User.findAll({ where: { meta: { [Op.contains]: { plan: 'pro' } } } });
Transaction with a savepoint#
await db.transaction(async (t) => {
await User.create({ email: 'grace@example.com', name: 'Grace' }, { transaction: t });
// A nested transaction is a SAVEPOINT; its failure undoes only its own work.
await db
.transaction(async (sp) => {
await User.destroy({ where: { id: 1 }, transaction: sp });
throw new Error('keep the row');
}, { transaction: t })
.catch(() => {});
});
Skip locked rows (SKIP LOCKED)#
A worker that claims rows from a queue table should pass over rows another transaction holds rather than wait for them. lock with skipLocked inside a transaction:await db.transaction(async (t) => {
await User.findAll({ where: { name: 'Ada' }, lock: { level: 'UPDATE', skipLocked: true }, transaction: t });
});
Type mapping for the portable descriptors: STRING → VARCHAR(255), auto-increment INTEGER → SERIAL, BOOLEAN → BOOLEAN, DATE → TIMESTAMP, UUID → UUID, JSON → JSON. The type comparison lines the major engines up side by side.Connection#
import { Prorm } from 'ts-prorm-orm';
// docker run -d --name my-omni -e POSTGRES_PASSWORD=… -p 5432:5432 google/alloydbomni
const d = new Prorm({
dialect: 'alloydbomni',
host: 'localhost',
database: 'postgres',
username: 'postgres',
password: process.env.OMNI_PASSWORD,
});
Plain pg wire, straight to the server: no connector, no Auth Proxy.What differs from managed AlloyDB#
| Managed AlloyDB (alloydb) | AlloyDB Omni (alloydbomni) |
|---|
| Superuser | none (highest role alloydbsuperuser) | postgres and alloydbadmin are superusers |
Untrusted languages (plpython3u, …) | refused by name | allowed |
| Google IAM database auth | iam option (googleIamTokenProvider + pgAuth) | refused — no Google control plane; passwords, or Active Directory / Kerberos via pg_hba |
| Columnar engine flags | set in the console | set with ALTER SYSTEM + restart (builders below) |
| Columnar engine functions | google_columnar_engine_* | same functions, same signatures (inherited) |
Passing iam throws at construction, before anything loads:new Prorm({
dialect: 'alloydbomni',
dialectOptions: {
iam: true,
},
});
// Error: AlloyDB Omni does not support Google IAM database authentication …
Columnar engine configuration#
On Omni you own the server flags. The engine is off until
google_columnar_engine.enabled is on, and both it and the column-store size
take effect only after a restart (docker restart <container>).
ALTER SYSTEM cannot run inside a transaction block — send each statement on
its own.d.buildEnableColumnarEngineSql({ memorySizeInMb: 2048 });
// [ "ALTER SYSTEM SET google_columnar_engine.enabled = 'on'",
// 'ALTER SYSTEM SET google_columnar_engine.memory_size_in_mb = 2048' ]
d.buildDisableColumnarEngineSql(); // … enabled = 'off'
d.buildColumnStoreMemorySql(1024); // at least 128 (server default 1024)
d.buildColumnarEngineStatusSql(); // SHOW google_columnar_engine.enabled
d.buildRecommendedColumnsQuery();
// SELECT database_name, schema_name, relation_name, column_name, estimated_size_in_bytes
// FROM g_columnar_recommended_columns
Once enabled, the inherited builders manage content exactly as on managed
AlloyDB:d.columnarEngineAdd('public.orders', ['total', 'region']);
d.columnarEngineRefresh('orders');
d.columnarEngineRecommend(); // run auto-columnarization now
d.columnarEngineRecommend('RECOMMEND_SIZE');
d.columnarEngineAddIndex('docs_emb'); // cache a ScaNN index
Google documents an upper bound of 70% of the instance's memory for the column
store; only the server can check that, so the builder enforces the lower bound
(128 MB) only.Refused, by name#
| Call | Why |
|---|
| `new Prorm({ | |
| dialect: 'alloydbomni', | |
| dialectOptions: { | |
| iam, | |
| }, | |
| })` | Omni has no Google IAM database authentication. |
buildColumnStoreMemorySql(n) with n < 128 or not an integer | Below the documented minimum. |
Everything the AlloyDB dialect refuses is still refused, except untrusted
procedural languages.Caveats / not verified#
Model integration (embedding(), ml_predict_row) needs Omni to be set up
to reach Vertex AI (a service account key); the dialect does not check that.
The statement that Omni has no Google IAM login is inferred from Omni's
authentication documentation, which describes password and Active
Directory / Kerberos only; no page states "IAM unsupported" in those words.
All SQL is asserted as strings in tests/dialects/alloydbomni.test.ts
without a server.
References#
Capabilities#
Computed from the code — capabilitiesOf() (src/transaction-support.ts),
whereSupportOf() (src/query-builders/expression-render.ts),
sqlObjectCapabilitiesOf() (src/sql-objects/capabilities.ts) and the
builders — by the scratch test described in the
capability matrix.| Capability | alloydbomni |
|---|
| Transactions atomic | yes |
| Savepoints | yes |
| Isolation | up to SERIALIZABLE |
| Transaction modes | read-only yes; deferrable yes; constraint deferral yes |
| RETURNING | RETURNING on INSERT |
| Upsert | INSERT … ON CONFLICT (…) DO UPDATE |
| JSON column | JSON (JSONB → JSONB) |
| Vector column | VECTOR(3) |
| Array column | INTEGER[] |
| WHERE builder | 62 operator keys; $and/$or/$not; $exists: yes; $in subquery: yes; expression operands: yes |
| SQL objects | family postgres: triggers yes; procedures yes; functions multiStatement; materialized views native; sequences yes; enums named; RLS policy |
| Streaming | queryStream() present; LISTEN present; createExtension() present |
See also#
alloydb — the parent dialect this one extends Modified at 2026-10-04 00:40:16