> ## Documentation Index
> Fetch the complete documentation index at: https://planetscale.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Connect a Bun application to Neki

> Bun SQL connections and replica routing

Bun includes a native Postgres client that can connect directly to Neki.

Before you start, you need:

* A Neki database with a ready branch.
* An application [role](/docs/neki/connecting/roles) for that branch. Use
  `pg_read_all_data` for read traffic and add `pg_write_all_data` when the
  application writes rows. These inherited data roles do not grant `CREATE` or
  `ALTER`, so application credentials cannot change the schema.
* A separate migration role, if you run schema changes against the branch. DDL
  requires the `postgres` inherited role. Neki restricts execution of the
  cross-router DDL barrier function `__neki.wait_for_ddl` to its `neki_viewer`
  role, so add `neki_viewer`, which requires `pg_read_all_data`, to the same
  role. Keep the migration credentials out of the application's runtime
  configuration.
* The **Primary** connection details from the database's **Connect** page.

Use the complete generated username. It contains the branch routing
information required by Neki.

## Create a Bun project

Install [Bun](https://bun.com/docs/installation), then initialize a project:

```bash theme={null}
bun init
```

## Add the connection string

Bun automatically loads local environment variables from `.env`. Copy the
connection URI from the **Connect** page:

```bash .env theme={null}
DATABASE_URL='postgresql://<USERNAME>:<PASSWORD>@<HOST>:5432/postgres?sslmode=verify-full'
```

Use the generated URI so reserved characters in the credentials remain URL
encoded. Bun supports `sslmode=verify-full` directly, verifying the server
certificate against trusted CAs and checking the hostname. Do not add
`sslrootcert=system`; Bun does not use it as a trust-store selector. Do not
commit the `.env` file.

## Connect and run a query

Use Bun's `sql` template literal:

```typescript index.ts theme={null}
import { sql } from 'bun'

const result = await sql`
  SELECT current_database() AS database, current_user AS role
`

console.log(result[0])
await sql.close()
```

Run the application:

```bash theme={null}
bun index.ts
```

## Apply schema changes

<Note>
  Framework migration commands send DDL through a normal Neki connection. The
  router fans that DDL out to the managed shards, but it does not create a
  managed schema-change workflow. Use a [schema-change
  workflow](/docs/neki/schema-changes) when you want Neki to prepare and coordinate
  an Online DDL change.
</Note>

Run migrations with the migration role described in the prerequisites. An
application role that inherits only `pg_read_all_data` and `pg_write_all_data`
cannot run `CREATE` or `ALTER`, so a migration that uses application
credentials fails on its first DDL statement.

Apply migration DDL with `psql` and the migration role so the client prints
PostgreSQL notices:

```bash theme={null}
psql "$MIGRATION_DATABASE_URL" -f <MIGRATION_FILE>
```

The router that commits the DDL emits a `NOTICE` containing the barrier call
for that transaction:

```text theme={null}
NOTICE: DDL is committed and the change is visible on this router; other routers may not see it yet. To wait until it is visible on every router, use __neki.wait_for_ddl(42, 7)
```

The schema and cluster versions belong to that transaction, and the notice is
the only place Neki reports them. Before you deploy application code that
depends on the new schema, run the emitted call verbatim on a primary
connection that uses the migration role:

```sql theme={null}
SELECT __neki.wait_for_ddl(42, 7);
```

The call returns after every router has applied both versions. A successful
migration only confirms that the DDL committed and is visible through the
router that ran it; it does not replace this cross-router barrier.

Some framework migration commands discard notices. Generate migration SQL
with the framework, but apply it with `psql` when the framework cannot preserve
the notice. If the notice is lost, its version pair cannot be reconstructed.

Bun SQL does not expose PostgreSQL notices. Apply migration SQL with `psql` so
you can capture and run the DDL barrier.

For read-only traffic, add the Neki replica startup option described in
[Primary and replica routing](/docs/neki/connecting#primary-and-replica-routing)
to the connection URI.

## Need help?

Get help from [the PlanetScale Support team](https://planetscale.com/contact?initial=support), or join our [Discord community](https://pscale.link/community) to see how others are using PlanetScale.
