Skip to content

PostgreSQL

This guide covers how to connect Tabula Lens to PostgreSQL databases, including self-hosted PostgreSQL, Supabase, and Neon.

Install the Tabula Lens Node package and the PostgreSQL driver:

Terminal window
npm i @tabula-lens/node pg

Set your database connection string as an environment variable:

Terminal window
DATABASE_URL="postgresql://user:password@localhost:5432/mydb"

You can also use the shorter postgres:// scheme:

Terminal window
DATABASE_URL="postgres://user:password@localhost:5432/mydb"

A PostgreSQL connection string has the following format:

postgresql://[user[:password]@][host][:port][/database][?parameters]

Components:

  • user - Database username
  • password - Database password (optional)
  • host - Database host (default: localhost)
  • port - Database port (default: 5432)
  • database - Database name
  • parameters - Additional connection parameters

Common connection parameters:

Terminal window
# SSL mode
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?sslmode=require"
# Connection pool settings
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?connectionLimit=10"
# Connection timeout
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?connectionTimeoutMillis=10000"
# Statement timeout
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?statement_timeout=30000"
# Application name (useful for monitoring)
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?application_name=tabula-lens"

PostgreSQL supports multiple SSL modes:

Terminal window
# Disable SSL (not recommended for production)
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?sslmode=disable"
# Allow SSL (non-encrypted connection allowed)
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?sslmode=allow"
# Prefer SSL (try SSL, fall back to non-SSL)
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?sslmode=prefer"
# Require SSL (SSL required, but certificate not verified)
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?sslmode=require"
# Verify CA (SSL required with CA verification)
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?sslmode=verify-ca"
# Verify Full (SSL required with CA and hostname verification)
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?sslmode=verify-full"

For production deployments, use sslmode=verify-full to ensure secure connections.

import { TabulaLens } from '@tabula-lens/node';
// Local development
const tabulaLens = new TabulaLens({
url: process.env.DATABASE_URL,
type: 'pg',
});
// Production
const tabulaLens = new TabulaLens({
url: process.env.DATABASE_URL,
type: 'pg',
logLevel: 'error',
logFormat: 'json',
sensitiveDataMasking: true,
enableRequestLogging: true,
});
// With SSL
const tabulaLens = new TabulaLens({
url: 'postgresql://user:password@localhost:5432/mydb?sslmode=verify-full',
type: 'pg',
logLevel: 'error',
});

Create a dedicated user with minimal required permissions:

-- Create a dedicated user for Tabula Lens
CREATE USER tabula_lens WITH PASSWORD 'secure_password';
-- Grant connect permission
GRANT CONNECT ON DATABASE mydb TO tabula_lens;
-- Grant usage on schema
GRANT USAGE ON SCHEMA public TO tabula_lens;
-- Grant select on specific tables
GRANT SELECT ON ALL TABLES IN SCHEMA public TO tabula_lens;
-- Grant select on future tables
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO tabula_lens;
  • Always use SSL in production: Set sslmode=require or sslmode=verify-full
  • Use strong passwords: Use environment variables or secret management
  • Limit network access: Use firewall rules, VPCs, or private networks
  • Rotate credentials regularly: Change database passwords periodically
  • Use connection pooling: Configure appropriate pool sizes
  • Monitor connections: Track connection usage and patterns

Supabase is a hosted PostgreSQL platform. Because Tabula Lens uses a standard PostgreSQL connection, it integrates directly with Supabase’s underlying database.

Retrieve your connection strings from the Supabase Dashboard under Project Settings → Database → Connection string.

Terminal window
# Direct connection (IPv6 only, or IPv4 with the add-on)
DATABASE_URL="postgresql://postgres.project-ref:[email protected]:5432/postgres"
# Session pooler — recommended for most Node.js servers (IPv4)
DATABASE_URL="postgresql://postgres.project-ref:[email protected]:5432/postgres"
# Transaction pooler — for serverless functions (IPv4)
DATABASE_URL="postgresql://postgres.project-ref:[email protected]:6543/postgres"
Direct Session Pooler Transaction Pooler
Best for Single long-lived server Multiple servers, IPv4 Serverless/edge
Port 5432 5432 6543
IPv4 support ❌ (add-on required)
Suitable for migrations

Use the session pooler for most server deployments. It supports IPv4 and handles multiple concurrent connections efficiently.

Use the transaction pooler (port 6543) for serverless platforms like Vercel Functions or AWS Lambda.

Use the direct connection only when you have a single long-lived server and either have native IPv6 connectivity or the Supabase IPv4 add-on enabled.

This is intentional: Tabula Lens is an admin database viewer designed for backend services with elevated privileges. To limit exposure, create a dedicated read-only role for the Tabula Lens connection:

-- Create a read-only role for Tabula Lens
CREATE ROLE tabula_lens_viewer WITH LOGIN PASSWORD 'your-password';
GRANT CONNECT ON DATABASE postgres TO tabula_lens_viewer;
GRANT USAGE ON SCHEMA public TO tabula_lens_viewer;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO tabula_lens_viewer;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO tabula_lens_viewer;

Then update your DATABASE_URL to authenticate as tabula_lens_viewer instead of postgres.

  • Protect the endpoint — Restrict access to the Tabula Lens HTTP endpoint with authentication middleware. See the authentication guides for patterns.
  • Never expose the connection string to the clientDATABASE_URL should only be used in server-side code.
  • IPv4 by default for pooler — If your server does not have native IPv6, use the session or transaction pooler. Both support IPv4 without the add-on.
  • SSL is required — Supabase requires SSL for all database connections. The connection strings from the Supabase Dashboard already include the appropriate SSL configuration.
  • Migrations — Run migrations against the direct or session pooler connection. The transaction pooler (port 6543) does not support prepared statements required by most migration tools.

Neon is a serverless PostgreSQL database with branching, autoscaling, and scale-to-zero. Tabula Lens connects to Neon using a standard PostgreSQL connection string — no additional drivers or configuration are required.

A Neon account with a project created. Your connection strings are available in the Neon Console under your project’s Connection Details.

Neon provides two connection types. Both are standard PostgreSQL URLs that work directly with Tabula Lens:

Terminal window
# Direct connection — long-running servers, migrations
DATABASE_URL="postgresql://user:[email protected]/neondb?sslmode=require"
# Pooled connection — serverless functions, high-traffic
DATABASE_URL="postgresql://user:[email protected]/neondb?sslmode=require"

The pooled hostname appends -pooler before the region segment; everything else is identical.

Direct Pooled
Best for Long-running servers Serverless, high-traffic
Concurrent connections Limited by compute Up to 10,000
Hostname pattern ep-xxx.region.aws.neon.tech ep-xxx-pooler.region.aws.neon.tech
Suitable for migrations ✅ Yes ❌ No

Use the direct connection when running on Express, Railway, Render, Fly.io, or any long-lived server process.

Use the pooled connection when running on Vercel Functions, AWS Lambda, or any serverless platform.

  • SSL is required — All Neon connections must include ?sslmode=require. Connections without it will be rejected by Neon’s servers.
  • Cold-start delay — Neon scales to zero when idle. The first connection after an inactivity period may have a brief delay while the compute instance resumes. Subsequent connections are immediate.
  • Vercel deployments — Use the pooled connection string. Vercel Functions are short-lived and benefit from Neon’s built-in connection pooler.
  • Migrations — Always run migrations against the direct connection string. The Neon pooler does not support the prepared statements used by most migration tools.

Connection refused

Ensure PostgreSQL is running and accessible. Check your firewall settings and verify the host and port in your connection string.

SSL errors

Verify your SSL configuration matches your PostgreSQL server’s SSL settings. For development, you can use sslmode=disable (not recommended for production).

ECONNREFUSED or timeout when connecting to the direct host

Your network likely does not support IPv6. The direct connection host (db.project-id.supabase.co) resolves to an IPv6 address by default. Switch to the session pooler connection string, which uses IPv4.

prepared statement "..." already exists error

This occurs when using the transaction pooler (port 6543) with clients that use prepared statements, such as Prisma or migration tools. Switch to the direct or session pooler connection for these clients.

SSL connection is required error

Add ?sslmode=require to your connection string. Neon requires SSL for all connections and will reject plain TCP connections.

Timeout on the first request after a period of inactivity

Neon scales to zero when idle. The first request triggers a cold start, which takes a few seconds to resume the compute instance. This is expected behavior — subsequent requests connect immediately once the instance is warm.