Initial UUID support (#183)
As much as I like the simplicity of auto incrementing integers as primary key, there are cases where a UUID is more suitable. To make this implementation database independent, the UUIDs are computed on the application layer using UUID v7 to maintain sorting by primary key.
When you're creating a new entity, you can choose the primary key type:
CleanShot.2025-06-12.at.09.47.13.mp4
Alternatively, you can overwrite the default primary key type by heading to the advances settings: Top right Avatar ➝ Settings ➝ Data ➝ Default Primary Format:
Postgres: choose between pg
, postgres
or create your own (#182)
There several ways to connect to your Postgres database, and so bknd shouldn't put a limit on that. You can now choose to connect using pg
, postgres
or create your own based on a kysely dialect!
import { pg, postgresJs } from "@bknd/postgres";
const usingPg = pg({ connectionString: "postgresql://..." });
const usingPostgresJs = postgresJs("postgresql://...");
Postgres offerings such as Neon and Xata have their own serverless driver. You can now create your custom Postgres connection by just specifying the kysely dialect:
import { createCustomPostgresConnection } from "@bknd/postgres";
import { CustomPostgresDialect } from "<somewhere>";
const custom = createCustomPostgresConnection(CustomPostgresDialect);
const connection = custom({ /* your dialects constructor args */ });
See the Postgres docs, the package overview or examples for neon and xata.
Added Cloudflare D1 Read Replication (#181)
Cloudflare D1 now offers read replication (currently in beta) to reduce read latency. This works by starting a D1 session with a specific bookmark. You can now turn this on:
import { serve } from "bknd/adapter/cloudflare";
export default serve({
mode: "fresh", // recommended
d1: {
session: true,
}
});
Note that you have to enable read replication on your D1 instance first in order for this to take effect. Read more on the docs how to tune the settings.
Docs: Added bknd.config.ts
(#180)
There has been quite an update on the docs on how to extend bknd using bknd.config.ts
. The configuration file is meant as a single entry point for your app as well as the CLI. With the CLI, you can spin up an instance without starting your app, add or change users, and in the future perform even more actions. To make sure both connect to the same source, the config file comes in handy.
It also allows to have a central point where to specify event listeners and additional route configuration. For every app event, you inject your custom logic and specify whether to block the execution (sync
) flow or not (async
). This allows to e.g. add custom checks and abort an update of an entry if the given condition is not met.
// bknd.config.ts
import { DatabaseEvents } from "bknd/data";
import type { BkndConfig } from "bknd/adapter";
export default {
// ...
onBuilt: async (app) => {
app.emgr.onEvent(
DatabaseEvents.MutatorUpdateBefore,
async (event) => {
const { entity, entityId, data } = event.params;
console.log(`Updating ${entity.name} #${entityId} with`, data);
},
"sync", // or "async" if you don't want to block the update
);
},
} as const satisfies BkndConfig;
Since this logic is placed in bknd.config.ts
this listener will also be executed when you run npx bknd run
.
Other Changes
- repo chores: fixed root dir, removed unused class, added .env.example by @dswbx in #176
- fix: lock hono version because of changed header setting in 4.7.7 by @dswbx in #179
Full Changelog: v0.13.0...v0.14.0