Bun.sql, so you don’t need to install a driver.
In this guide, you connect Bun to ClickHouse Managed Postgres over verified TLS, create a table, run queries and a transaction, and serve the rows over HTTP with Bun.serve.
Prerequisites
- Bun 1.4 or later. This guide was tested with Bun 1.4.2 and Postgres 18.
- A ClickHouse Cloud account.
psql, to create the database. You can also run theCREATE DATABASEstatement in the SQL console.
Create a ClickHouse Managed Postgres service
In the ClickHouse Cloud console, click New service and select Postgres. The instance is ready in a few minutes. See the quickstart for a walkthrough.Get your connection details
Open your service and click Connect in the left sidebar. Keep Directly selected and turn on Use SSL. The URL now ends withsslmode=verify-full&sslrootcert=.... Click Download CA certificate to download the CA certificate for your instance.
This guide connects directly on port 5432. A Bun.serve app is a long-running process, and Bun.sql keeps its own connection pool, so a server-side pooler isn’t needed. If you run many short-lived Bun processes, see Connect through PgBouncer.
Set up the project
Create a project:Configure the connection
Move the CA certificate you downloaded into the project and rename it toca-certificate.pem:
<PASSWORD> and the host with the values from the Connect modal:
guide_bun database to .env, creating the file if it doesn’t exist. Bun loads .env automatically, and the sql export from bun reads DATABASE_URL:
.env
.env out of version control.
Add these scripts to package.json, merging them into the scripts block if it already exists. They pass the CA certificate to Bun through NODE_EXTRA_CA_CERTS:
package.json
How Bun verifies the server certificate
sslmode=verify-fullmakesBun.sqlcheck both the certificate chain and the host name.- Don’t copy the
sslrootcertparameter from the console URL.Bun.sqldoesn’t read it. It forwards it to the server as a runtime setting, and the connection fails withunrecognized configuration parameter "sslrootcert". NODE_EXTRA_CA_CERTSmust be set in the environment when Bun starts. Bun doesn’t read it from.env, which is why it’s in the scripts.- In Bun 1.4.2, passing the downloaded certificate through the
tls: { ca }option ofSQLfails withcertificate signature failure. UseNODE_EXTRA_CA_CERTSinstead.
Create a table
Createsetup.ts. It prints the TLS state of the session and creates a todos table:
setup.ts
Query the database
Bun.sql uses tagged templates. Every interpolated value is sent as a bind parameter, so it’s safe to pass user input. Create queries.ts:
queries.ts
sql.begin runs the callback in a transaction. It commits when the callback returns and rolls back if it throws.
Run it:
Serve the rows over HTTP
Createserver.ts with a /todos endpoint that lists and creates rows:
server.ts
Verify
Open http://localhost:3106/todos in your browser to see all rows. The response looks like this, formatted for readability:Connect through PgBouncer
If you run many short-lived Bun processes, connect through the bundled PgBouncer instead. Select via PgBouncer in the Connect modal and change the port inDATABASE_URL to 6432. The CA certificate and sslmode=verify-full stay the same.
PgBouncer runs in transaction pooling mode. Bun.sql uses named prepared statements by default, and in our tests they worked through PgBouncer with no errors. If you see prepared statement does not exist errors, create the client with prepare: false:
prepare as an option, not in the URL. Like sslrootcert, a prepare=false URL parameter is forwarded to the server and rejected.
Next steps
- Connection: connection strings, PgBouncer, and TLS
- Settings: change Postgres and PgBouncer parameters
- Read replicas: scale reads
- Bun SQL documentation: the full
Bun.sqlAPI