Skip to main content
RapidDev - Software Development Agency
bolt-ai-integrationsBolt Chat + API Route

How to Integrate Bolt.new with PostgreSQL

The standard pg (node-postgres) driver uses TCP and fails in Bolt's WebContainer during development. PostgreSQL in Bolt.new works through three HTTP-based alternatives: Bolt Database (built-in, auto-provisioned Supabase PostgreSQL), Supabase (@supabase/supabase-js via PostgREST), or Neon (@neondatabase/serverless via HTTP/WebSocket). All three work in the preview. After deployment to Netlify, standard pg driver connects normally — TCP works in a real Node.js runtime.

What you'll learn

  • Why the standard pg driver fails in Bolt's WebContainer and which HTTP-based alternatives work
  • How to use Bolt Database (built-in auto-provisioned PostgreSQL) for the simplest setup
  • How to connect Supabase PostgreSQL using @supabase/supabase-js and PostgREST
  • How to use Neon serverless PostgreSQL with @neondatabase/serverless for HTTP/WebSocket access
  • How to use Prisma with Neon's HTTP adapter for type-safe queries that work in the WebContainer
Book a free consultation
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Intermediate18 min read20 minutesDatabaseApril 2026RapidDev Engineering Team
TL;DR

The standard pg (node-postgres) driver uses TCP and fails in Bolt's WebContainer during development. PostgreSQL in Bolt.new works through three HTTP-based alternatives: Bolt Database (built-in, auto-provisioned Supabase PostgreSQL), Supabase (@supabase/supabase-js via PostgREST), or Neon (@neondatabase/serverless via HTTP/WebSocket). All three work in the preview. After deployment to Netlify, standard pg driver connects normally — TCP works in a real Node.js runtime.

PostgreSQL in Bolt.new: Three HTTP Paths to the Same Database

PostgreSQL is the default database choice for most web apps — it is what Supabase, Neon, Railway, and Bolt's own database are built on. The challenge in Bolt.new is architectural: the standard node-postgres driver (pg) communicates with PostgreSQL servers via raw TCP connections on port 5432. Bolt's WebContainer virtualizes Node.js inside the browser and cannot make raw TCP connections. When you install pg and call pool.query('SELECT...'), the TCP connection attempt fails silently or throws a connection refused error during development.

The good news: PostgreSQL has the most HTTP-compatible ecosystem of any database in the Bolt world. Three services provide HTTP-over-PostgreSQL access that works in the WebContainer. Bolt Database, introduced in September 2025, is built-in — if you ask Bolt to add a database to your project, it provisions one automatically using Supabase infrastructure. No signup, no configuration, it just works. Supabase exposes its PostgreSQL instances through PostgREST, an HTTP REST API layer, accessible via @supabase/supabase-js. Neon provides a serverless PostgreSQL driver (@neondatabase/serverless) that switches between HTTP and WebSocket modes — the HTTP mode works in WebContainers.

For apps that specifically need raw SQL through the pg driver — complex JOINs, stored procedures, custom functions — deploy to Netlify and use pg with a Neon, Supabase, or Railway connection string. After deployment, the TCP connection works normally. The WebContainer limitation applies only during local Bolt development, not production.

Integration method

Bolt Chat + API Route

PostgreSQL connects to Bolt.new through HTTP-based database clients — the standard pg driver uses TCP and fails in the WebContainer during development, but three HTTP-compatible alternatives work in the preview: Bolt Database (built-in, uses Supabase's PostgREST over HTTP), @supabase/supabase-js (PostgREST HTTP client), and @neondatabase/serverless (HTTP and WebSocket modes). After deploying to Netlify or Bolt Cloud, the standard pg driver works in a real Node.js environment. This tutorial covers all three HTTP-based options and explains the standard pg approach for post-deployment.

Prerequisites

  • A Bolt.new project — Vite + React works for Supabase/Neon, Next.js needed for API routes with raw SQL
  • For Bolt Database: no prerequisites — Bolt provisions it automatically when you ask
  • For Supabase: a Supabase account at supabase.com (free tier includes 2 projects and 500MB storage)
  • For Neon: a Neon account at neon.tech (free tier includes 3 projects and 0.5GB storage)
  • Understanding that the pg driver works only after deploying to Netlify — use HTTP-based clients during Bolt development

Step-by-step guide

1

Choose Your PostgreSQL Path and Understand the TCP Limitation

Before writing any code, understand the WebContainer constraint and pick the right approach for your use case. Bolt's WebContainer runs Node.js inside a browser tab via WebAssembly. The browser security model prevents raw TCP socket connections, which means the standard pg (node-postgres) driver cannot connect to PostgreSQL servers during development. When you run pool.query() in the Bolt preview, the call will hang or throw a connection error — not because your connection string is wrong, but because TCP is blocked at the WebAssembly layer. Here is the decision tree for choosing your PostgreSQL approach: **Option 1: Bolt Database (auto-provisioned)** — Best for new projects where you want zero setup. Bolt provisions a Supabase PostgreSQL database automatically. Use @supabase/supabase-js for queries. Works in preview. Limitation: Supabase JS client works only with Vite projects per current Bolt documentation, not Next.js within Bolt's WebContainer. **Option 2: Supabase + @supabase/supabase-js** — Best for apps needing auth, real-time, and storage alongside the database. Use with Vite. PostgREST exposes your tables as REST endpoints over HTTP. Works in preview. **Option 3: Neon + @neondatabase/serverless** — Best for raw SQL with Vite or Next.js. Neon's serverless driver has HTTP mode that works in WebContainer. Supports tagged template literals for safe SQL. Works in preview. **Option 4: pg driver after deployment** — Best when you need connection pooling, transactions, or stored procedures that require the full pg driver. Write the code in Bolt, test by deploying to Netlify. This is the path for production apps with complex query requirements. All four paths lead to the same PostgreSQL — the difference is the client library and when you can test it. For most Bolt apps, start with Option 2 or 3.

Bolt.new Prompt

Show me the three ways to connect to PostgreSQL in Bolt.new: (1) using @supabase/supabase-js with Supabase, (2) using @neondatabase/serverless with Neon, (3) using the standard pg driver for post-deployment only. Create a lib/ folder with three separate database client files: supabase-client.ts, neon-client.ts, and pg-client.ts. Each exports a query function. Include comments explaining when each approach works (preview vs deployment-only).

Paste this in Bolt.new chat

lib/db-options-overview.ts
1// Summary of PostgreSQL options in Bolt.new:
2
3// OPTION 1: Supabase (works in Bolt preview - Vite projects only)
4// Uses PostgREST over HTTP
5import { createClient } from '@supabase/supabase-js';
6const supabase = createClient(
7 import.meta.env.VITE_SUPABASE_URL,
8 import.meta.env.VITE_SUPABASE_ANON_KEY
9);
10// Usage: await supabase.from('products').select('*')
11
12// OPTION 2: Neon serverless (works in Bolt preview)
13// Uses HTTP transport
14import { neon } from '@neondatabase/serverless';
15const sql = neon(import.meta.env.VITE_DATABASE_URL);
16// Usage: await sql`SELECT * FROM products WHERE id = ${id}`
17
18// OPTION 3: Standard pg driver (FAILS in Bolt preview - TCP blocked)
19// Use ONLY in deployed Next.js API routes, NOT in browser/Vite
20import { Pool } from 'pg';
21const pool = new Pool({ connectionString: process.env.DATABASE_URL });
22// Usage: await pool.query('SELECT * FROM products WHERE id = $1', [id])
23// Error in Bolt preview: ECONNREFUSED / timeout (TCP blocked by WebContainer)

Pro tip: If you're not sure which option to use, start with Neon + @neondatabase/serverless. It works in both Vite and Next.js projects, supports raw SQL with parameterized queries, and has a generous free tier (3 projects, 0.5GB storage, unlimited queries).

Expected result: You understand which PostgreSQL connection method to use for your project type and have chosen between Bolt Database, Supabase, Neon serverless, or standard pg for post-deployment.

2

Option A: Set Up Neon Serverless PostgreSQL

Neon is a serverless PostgreSQL provider that offers the best balance of flexibility and WebContainer compatibility for Bolt apps. Create a free account at neon.tech and provision a new database. On the Neon dashboard, find your connection string under 'Connection Details' — it looks like postgresql://user:password@ep-something.us-east-2.aws.neon.tech/neondb. Install @neondatabase/serverless. The package exports a neon function that creates a tagged template literal query executor using HTTP mode — no TCP, fully WebContainer compatible. Import and initialize neon() with your connection string from an environment variable. Neon's tagged template literal syntax automatically parameterizes query values, preventing SQL injection. Write queries like: const users = await sql`SELECT * FROM users WHERE email = ${email}`. The ${email} is a parameterized value, not string interpolation — safe and correct. For multiple results, the response is an array of row objects with typed properties matching your column names. For Next.js projects using Neon with API routes: use the neon function in your Route Handler files (app/api/*/route.ts). For Vite projects: you can use neon directly in client components only if you include the DATABASE_URL with the VITE_ prefix — but this exposes your database credentials client-side. Prefer putting Neon queries in a server context or API layer whenever possible. Neon also supports Prisma through the @prisma/adapter-neon package, which uses HTTP/WebSocket instead of TCP — making Prisma + Neon work in the WebContainer for a fully type-safe ORM experience.

Bolt.new Prompt

Set up Neon PostgreSQL with @neondatabase/serverless. Install the package. Create a .env with DATABASE_URL=your_neon_connection_string (use the pooler connection string from Neon dashboard for serverless). Create lib/db.ts that exports an initialized neon client as sql. Create a Next.js API route at app/api/users/route.ts using the neon client: GET returns all users (SELECT id, name, email, created_at FROM users ORDER BY created_at DESC LIMIT 50), POST accepts {name, email} in request body and inserts a new user (INSERT INTO users (name, email) VALUES ($1, $2) RETURNING *). Return results as JSON. Handle database errors with appropriate status codes. Create a users table migration at db/migrations/001_create_users.sql.

Paste this in Bolt.new chat

lib/db.ts
1// lib/db.ts — Neon serverless client
2import { neon } from '@neondatabase/serverless';
3
4const connectionString = process.env.DATABASE_URL;
5
6if (!connectionString) {
7 throw new Error('DATABASE_URL environment variable is required');
8}
9
10export const sql = neon(connectionString);
11
12// Type helper for rows
13export type QueryResult<T> = T[];
14
15// app/api/users/route.ts — Using neon sql tag
16import { NextResponse } from 'next/server';
17import { sql } from '@/lib/db';
18
19interface User {
20 id: number;
21 name: string;
22 email: string;
23 created_at: string;
24}
25
26export async function GET() {
27 try {
28 const users = await sql<User[]>`
29 SELECT id, name, email, created_at
30 FROM users
31 ORDER BY created_at DESC
32 LIMIT 50
33 `;
34 return NextResponse.json(users);
35 } catch (error: unknown) {
36 const e = error as { message: string };
37 return NextResponse.json({ error: e.message }, { status: 500 });
38 }
39}
40
41export async function POST(request: Request) {
42 try {
43 const { name, email } = await request.json();
44 if (!name || !email) {
45 return NextResponse.json({ error: 'name and email required' }, { status: 400 });
46 }
47 const [user] = await sql<User[]>`
48 INSERT INTO users (name, email)
49 VALUES (${name}, ${email})
50 RETURNING *
51 `;
52 return NextResponse.json(user, { status: 201 });
53 } catch (error: unknown) {
54 const e = error as { message: string; code?: string };
55 if (e.code === '23505') {
56 return NextResponse.json({ error: 'Email already exists' }, { status: 409 });
57 }
58 return NextResponse.json({ error: e.message }, { status: 500 });
59 }
60}

Pro tip: Neon provides two connection strings: the standard postgres:// URI and a pooler connection string (uses pgBouncer). Use the pooler connection string (port 5432 with -pooler in the hostname) for serverless environments — it handles connection pool management better for short-lived serverless function executions.

Expected result: The Neon @neondatabase/serverless client connects over HTTP in the Bolt preview. API routes execute SQL queries and return results. The users table is created via the migration SQL.

3

Option B: Set Up Supabase PostgreSQL with Real-Time

Supabase is the recommended PostgreSQL option for Vite-based Bolt projects. Supabase provides PostgreSQL via PostgREST (a REST API layer) and real-time subscriptions via WebSocket — both protocols work in the WebContainer. Create a Supabase project at supabase.com, find your project URL and anon key in Settings → API. Install @supabase/supabase-js. Initialize the client with your Supabase URL and anon key (the anon key is safe to use client-side — it's a public key protected by Row Level Security). The client's .from() method chains query operators: .select(), .eq(), .gt(), .order(), .limit() for filtering; .insert(), .update(), .delete() for mutations; .subscribe() for real-time. Create your database tables either through Supabase's Table Editor GUI (supabase.com → your project → Table Editor) or by prompting Bolt to generate and run SQL migrations. Enable RLS (Row Level Security) on tables that contain user-specific data — without RLS, anyone with your anon key can read all rows. Bolt generates RLS policies automatically when you describe your access rules. Supabase real-time works through WebSocket channels. Subscribe to table changes: supabase.channel('orders').on('postgres_changes', {event: 'INSERT', schema: 'public', table: 'orders'}, callback).subscribe(). The callback receives a payload with the new row data. Unsubscribe in React's useEffect cleanup to prevent memory leaks. Important Bolt-specific limitation: @supabase/supabase-js in the WebContainer works with Vite projects. For Next.js API routes that need direct PostgreSQL access with complex queries, use @neondatabase/serverless instead of Supabase's client library.

Bolt.new Prompt

Connect this Vite + React app to Supabase PostgreSQL. Install @supabase/supabase-js. Create lib/supabase.ts with a configured Supabase client using VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY env vars. Create a .env with both variables (I'll fill in values from Supabase dashboard). Define TypeScript interfaces for a todos table: { id: string, user_id: string, title: string, completed: boolean, created_at: string }. Create a useTodos hook that: fetches todos with supabase.from('todos').select('*').order('created_at'), subscribes to INSERT and UPDATE events on the todos table for real-time updates, returns {todos, loading, error, addTodo, toggleTodo, deleteTodo}. Also create the Supabase migration SQL to create the todos table with RLS policies (users see only their own todos).

Paste this in Bolt.new chat

lib/supabase.ts
1// lib/supabase.ts
2import { createClient } from '@supabase/supabase-js';
3
4const supabaseUrl = import.meta.env.VITE_SUPABASE_URL;
5const supabaseAnonKey = import.meta.env.VITE_SUPABASE_ANON_KEY;
6
7if (!supabaseUrl || !supabaseAnonKey) {
8 throw new Error('Missing VITE_SUPABASE_URL or VITE_SUPABASE_ANON_KEY');
9}
10
11export const supabase = createClient(supabaseUrl, supabaseAnonKey);
12
13// Migration SQL (run in Supabase SQL editor):
14/*
15CREATE TABLE todos (
16 id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
17 user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
18 title TEXT NOT NULL,
19 completed BOOLEAN NOT NULL DEFAULT false,
20 created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
21);
22
23ALTER TABLE todos ENABLE ROW LEVEL SECURITY;
24
25CREATE POLICY "Users see own todos" ON todos
26 FOR ALL USING (auth.uid() = user_id);
27*/
28
29// Real-time subscription pattern:
30// const channel = supabase
31// .channel('todos-changes')
32// .on('postgres_changes', {
33// event: '*',
34// schema: 'public',
35// table: 'todos',
36// filter: `user_id=eq.${userId}`
37// }, (payload) => {
38// if (payload.eventType === 'INSERT') setTodos(prev => [payload.new as Todo, ...prev]);
39// if (payload.eventType === 'UPDATE') setTodos(prev => prev.map(t => t.id === payload.new.id ? payload.new as Todo : t));
40// if (payload.eventType === 'DELETE') setTodos(prev => prev.filter(t => t.id !== payload.old.id));
41// })
42// .subscribe();
43//
44// return () => supabase.removeChannel(channel); // Cleanup

Pro tip: Always enable RLS on Supabase tables that store user data. A common Bolt mistake is creating tables without RLS — the anon key provides read access to the entire table without RLS, making all rows publicly readable to anyone with your VITE_SUPABASE_ANON_KEY.

Expected result: Supabase client connects over HTTP in the Bolt Vite preview. The todos table is created with RLS. The useTodos hook fetches and subscribes to real-time changes.

4

Post-Deployment: Using the Standard pg Driver

After deploying to Netlify or Bolt Cloud, the TCP restriction is lifted — your code runs in a real Node.js environment where pg connects normally to PostgreSQL. This opens up advanced database patterns not possible in the WebContainer: connection pooling, transactions, prepared statements, stored procedures, COPY commands for bulk operations, and listen/notify for pub/sub. For serverless deployments on Netlify (and Vercel), use a connection pooler in front of your PostgreSQL database. Serverless functions create a new Node.js process for each request — without pooling, each function invocation would open a new PostgreSQL connection, quickly exhausting the database's connection limit. Neon's pooler endpoint (add -pooler to hostname) or PgBouncer handles this automatically. Supabase also exposes a pooler connection string in its dashboard under Settings → Database → Connection pooling. The pg Pool pattern for Next.js API routes: create a connection pool in a module-level variable. Node.js caches module imports, so the Pool object persists across API route invocations in the same Lambda container — connections are reused rather than created fresh each time. Export the pool from a lib/db.ts file and import it in your API routes. For Prisma users: Prisma works excellently with PostgreSQL after deployment. Use @prisma/adapter-neon for Neon (works in both WebContainer HTTP mode and deployed TCP mode), or configure the standard prisma/client with DATABASE_URL pointing to your deployed database. Run prisma db push or prisma migrate deploy in your Netlify build command to apply schema changes on deployment.

Bolt.new Prompt

Set up the standard pg driver for PostgreSQL, intended for use after deployment (not Bolt preview). Create lib/pg-pool.ts that exports a Pool instance from the pg package, initialized with process.env.DATABASE_URL. Configure pool options: max: 5, idleTimeoutMillis: 30000, connectionTimeoutMillis: 5000. Export a query helper function. Create a Next.js API route at app/api/products/route.ts using the pool. Add a comment at the top of pg-pool.ts noting this only works after deployment to Netlify or Vercel, not in the Bolt WebContainer preview.

Paste this in Bolt.new chat

lib/pg-pool.ts
1// lib/pg-pool.ts
2// NOTE: This module uses TCP connections and only works AFTER DEPLOYMENT
3// to Netlify, Vercel, or similar Node.js environments.
4// In Bolt's WebContainer preview, queries will fail with ECONNREFUSED or timeout.
5import { Pool } from 'pg';
6
7const connectionString = process.env.DATABASE_URL;
8
9if (!connectionString) {
10 throw new Error('DATABASE_URL environment variable is required');
11}
12
13export const pool = new Pool({
14 connectionString,
15 max: 5, // Max connections in pool (keep low for serverless)
16 idleTimeoutMillis: 30000, // Release idle connections after 30s
17 connectionTimeoutMillis: 5000, // Fail fast if connection takes >5s
18 ssl: { rejectUnauthorized: false }, // Required for Neon/Supabase/RDS
19});
20
21// Graceful shutdown
22process.on('SIGTERM', () => pool.end());
23
24// Helper for parameterized queries
25export async function query<T>(
26 text: string,
27 params?: (string | number | boolean | null | undefined)[]
28): Promise<T[]> {
29 const { rows } = await pool.query(text, params);
30 return rows as T[];
31}
32
33// Transaction helper
34export async function withTransaction<T>(
35 callback: (client: { query: (text: string, params?: unknown[]) => Promise<{ rows: T[] }> }) => Promise<T>
36): Promise<T> {
37 const client = await pool.connect();
38 try {
39 await client.query('BEGIN');
40 const result = await callback(client);
41 await client.query('COMMIT');
42 return result;
43 } catch (error) {
44 await client.query('ROLLBACK');
45 throw error;
46 } finally {
47 client.release();
48 }
49}

Pro tip: For PostgreSQL on Neon, Supabase, or RDS, always include ssl: { rejectUnauthorized: false } in your Pool configuration or set sslmode=require in the connection string. Cloud PostgreSQL providers require SSL connections and pg will fail with 'SSL off' error without this setting.

Expected result: lib/pg-pool.ts is set up with connection pooling configured for serverless deployment. The module is clearly commented as deployment-only. After deploying to Netlify with DATABASE_URL set, PostgreSQL queries execute successfully.

Common use cases

Full-Stack App with Bolt's Built-In Database

The fastest path to a working PostgreSQL database in Bolt.new: ask Bolt to add a database and it automatically provisions a Supabase PostgreSQL instance, generates schema, creates RLS policies, and configures the client. No account signup, no configuration. Start building your app in minutes with a production-ready PostgreSQL database.

Bolt.new Prompt

Add a database to this app using Bolt's built-in database. Create a products table with columns: id (uuid primary key), name (text not null), description (text), price (numeric not null), category (text), stock_quantity (integer default 0), created_at (timestamp default now()). Add RLS so only authenticated users can read products and only admins can write. Generate TypeScript types for the products table. Create a getProducts() function and a createProduct(product) function using the Supabase client.

Copy this prompt to try it in Bolt.new

Neon Serverless PostgreSQL with Raw SQL

Use Neon's serverless PostgreSQL for apps that need raw SQL queries — JOINs, aggregations, complex WHERE clauses — with an HTTP-compatible driver that works in Bolt's WebContainer. Neon's @neondatabase/serverless client uses HTTP mode for single queries and WebSocket mode for transactions.

Bolt.new Prompt

Set up Neon PostgreSQL with @neondatabase/serverless. Install the package. Create lib/db.ts that exports a neon function initialized with DATABASE_URL from env. Create an API route at app/api/products/route.ts that uses the neon tagged template literal to run: GET - SELECT id, name, price, category FROM products WHERE ($1::text IS NULL OR category = $1) ORDER BY created_at DESC LIMIT 50 with the category query param as $1. POST - INSERT INTO products (name, description, price, category) VALUES ($1, $2, $3, $4) RETURNING * with values from request body. Return results as JSON. Use TypeScript types for Product.

Copy this prompt to try it in Bolt.new

Supabase PostgreSQL with Real-Time Subscriptions

Use Supabase for PostgreSQL with real-time features — subscribe to table changes and update your UI automatically when other users insert or update rows. Supabase's @supabase/supabase-js uses WebSocket for real-time, which works in Bolt's WebContainer. This is the best choice for collaborative apps, dashboards, and live data feeds.

Bolt.new Prompt

Connect to Supabase PostgreSQL with real-time updates. Create a lib/supabase.ts that initializes the Supabase client with VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY. Create an OrdersDashboard component that: fetches all pending orders on mount with supabase.from('orders').select('*').eq('status', 'pending'), subscribes to INSERT events on the orders table to add new orders to state in real time, subscribes to UPDATE events to update order status when changed, unsubscribes on component unmount. Show orders in a table with columns: order ID, customer name, amount, status, created time. New orders appear at the top without page refresh.

Copy this prompt to try it in Bolt.new

Troubleshooting

ECONNREFUSED or connection timeout when running PostgreSQL queries in the Bolt preview

Cause: The pg driver (or any TCP-based PostgreSQL client) is attempting a TCP connection to PostgreSQL's port 5432. Bolt's WebContainer blocks all TCP socket connections.

Solution: Switch to an HTTP-based alternative for development: @neondatabase/serverless (HTTP mode) or @supabase/supabase-js (PostgREST). If you specifically need the pg driver, deploy to Netlify and test there. The same code works after deployment.

typescript
1// Replace pg driver (TCP, fails in Bolt):
2// import { Pool } from 'pg';
3// const pool = new Pool({ connectionString: process.env.DATABASE_URL });
4
5// With Neon serverless (HTTP, works in Bolt):
6import { neon } from '@neondatabase/serverless';
7const sql = neon(process.env.DATABASE_URL!);
8// await sql`SELECT * FROM users` — works in Bolt preview

Supabase client returns 'Failed to fetch' or CORS error in Bolt

Cause: The Supabase URL is incorrect, the VITE_SUPABASE_ANON_KEY is wrong, or the Supabase project is paused (Supabase pauses free projects after 1 week of inactivity).

Solution: Verify VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY match your project in supabase.com → Settings → API. If the project is paused, click 'Restore project' in the Supabase dashboard. Paused projects reject all API calls until restored.

typescript
1// Verify Supabase client initialization:
2console.log('Supabase URL:', import.meta.env.VITE_SUPABASE_URL?.substring(0, 30));
3// Should show: https://xxxxxxxxxxxx.supabase.co
4// If undefined, the VITE_SUPABASE_URL env var is missing from .env

Neon database returns 'endpoint is disabled' or connection string format error

Cause: Neon free tier endpoints sleep after 5 minutes of inactivity and wake on the next request (cold start takes 1-2 seconds). A connection string format error means a copy-paste issue with the connection string.

Solution: Neon cold starts are normal — the first query after inactivity takes 1-2 seconds longer. Handle this with a loading state in your UI. For the connection string, use the pooler endpoint from the Neon dashboard (labeled 'Pooled connection') to minimize cold start frequency.

Supabase RLS blocks all queries and returns empty arrays

Cause: Row Level Security is enabled on the table but no policy allows the current user (or anonymous user with the anon key) to read rows.

Solution: Add an appropriate RLS policy for your use case. For development, temporarily disable RLS with ALTER TABLE tablename DISABLE ROW LEVEL SECURITY; (never in production). For production, add a policy: CREATE POLICY 'allow_all' ON tablename FOR SELECT USING (true); for public data, or auth.uid() = user_id for user-specific rows.

typescript
1-- Quick RLS debug: add a permissive select policy for testing
2CREATE POLICY "allow_read" ON your_table
3 FOR SELECT USING (true);
4-- Replace with appropriate policy for production:
5-- FOR SELECT USING (auth.uid() = user_id);

Best practices

  • Use @neondatabase/serverless for Bolt projects that need raw SQL — it works in both WebContainer (HTTP mode) and deployed environments, and has the most straightforward migration path to standard pg driver
  • Always enable RLS on Supabase tables — without RLS, your VITE_SUPABASE_ANON_KEY grants public read access to all table rows to anyone who inspects your client-side bundle
  • Use connection pooling (Neon pooler URL or PgBouncer) for serverless deployments — serverless functions create new processes per request and will exhaust PostgreSQL's connection limit without a pooler
  • Store PostgreSQL connection strings in environment variables without NEXT_PUBLIC_ or VITE_ prefix — connection strings contain credentials that must never be exposed in client-side code
  • Include ssl: { rejectUnauthorized: false } in pg Pool configuration for cloud PostgreSQL providers — without SSL configuration, connections to Neon, Supabase, and most managed PostgreSQL services will fail
  • For Supabase real-time subscriptions, always clean up channels in useEffect return functions — memory leaks from unsubscribed channels are a common Bolt app issue
  • Test with Neon's free tier for development and production — Neon's scale-to-zero model means you pay nothing for inactive databases, making it cost-effective for low-traffic Bolt apps

Alternatives

Frequently asked questions

Why does pg fail in Bolt's WebContainer but work after deploying to Netlify?

Bolt's WebContainer runs Node.js inside a browser tab using WebAssembly. Browsers cannot make raw TCP socket connections — a security restriction that also prevents WebContainers from doing so. PostgreSQL's pg driver communicates via TCP to port 5432. After deploying to Netlify, your code runs in real Node.js on AWS Lambda with full networking capabilities, so TCP connections work normally. This is not a bug in pg or in your code.

Which PostgreSQL provider works best with Bolt.new?

Neon and Supabase are the top choices. Neon is best for Next.js projects and raw SQL needs — @neondatabase/serverless HTTP mode works in WebContainers and supports parameterized queries. Supabase is best for Vite projects with real-time requirements — @supabase/supabase-js uses PostgREST and WebSocket, both WebContainer-compatible, plus includes auth, storage, and edge functions. Bolt Database (auto-provisioned in Bolt V2+) is the easiest path for new projects — no setup required.

Can I use Prisma with PostgreSQL in Bolt.new?

Yes, with Neon's HTTP adapter. Use @prisma/adapter-neon which communicates via HTTP and WebSocket instead of TCP — this makes Prisma work in Bolt's WebContainer. Configure your Prisma client with the neonAdapter and VITE_DATABASE_URL. Standard Prisma with pg adapter uses TCP and only works after deployment. Drizzle ORM also works with Neon serverless and is a popular alternative.

Does Supabase work with Next.js in Bolt.new?

Per current Bolt documentation, @supabase/supabase-js connects successfully in Vite projects but has reported issues in Next.js projects within the Bolt WebContainer. For Next.js projects in Bolt, use @neondatabase/serverless instead of Supabase's JS client for database queries. You can still use Supabase for authentication in Next.js apps using @supabase/auth-helpers-nextjs — the database query limitation applies to the supabase.from() table operations.

How do I run database migrations in Bolt.new?

For Supabase: go to your Supabase project dashboard → SQL Editor, paste and run your CREATE TABLE statements. For Neon: use the Neon SQL editor in the dashboard, or run psql locally with the Neon connection string. In Bolt itself, you can prompt Bolt to generate migration SQL files and then paste them into your database provider's SQL editor. Bolt does not automatically run SQL migrations — you apply them manually in the database provider's console.

RapidDev

Talk to an Expert

Our team has built 600+ apps. Get personalized help with your project.

Book a free consultation

Need help with your project?

Our experts have built 600+ apps and can accelerate your development. Book a free consultation — no strings attached.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.