Skip to content

Data Table PostgreSQL Overview

The data-table-postgres package connects the data-table query toolkit to PostgreSQL via the pg driver. PostgreSQL is the recommended database for production Remix applications that need scalability, advanced features, or multi-server deployments.

When to Use PostgreSQL

Use CasePostgreSQL Fits?
Production web applicationsYes --- designed for concurrent access, replication, and high availability.
Multi-server deploymentsYes --- networked connections and advisory locks for safe migrations.
Advanced queries (CTEs, window functions, JSONB)Yes --- PostgreSQL has the richest SQL feature set.
Local developmentYes, but SQLite is simpler if you want zero setup.
Embedded / edge / serverlessMaybe --- requires a running PostgreSQL server or a hosted service.

Quick Setup

ts
import { Pool } from 'pg'
import { createPostgresDatabaseAdapter } from 'remix/data-table-postgres'
import { createDatabase, table, column as c } from 'remix/data-table'

// Create a connection pool
let pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20,
})

// Create the adapter and database
let adapter = createPostgresDatabaseAdapter(pool)
let db = createDatabase(adapter)

// Define a table
let users = table({
  name: 'users',
  columns: {
    id: c.uuid().primaryKey().defaultSql('gen_random_uuid()'),
    email: c.varchar(255).notNull().unique('users_email_uq'),
    name: c.text().notNull(),
    createdAt: c.timestamp({ withTimezone: true }).notNull().defaultNow(),
  },
})

// Query
let all = await db.findMany(users)

What is a connection pool?

A connection pool maintains a set of open database connections that are reused across requests. This avoids the overhead of opening a new TCP connection for every query. Always use a Pool in production.

Key Advantages Over SQLite

FeaturePostgreSQLSQLite
Concurrent writesYesSingle writer only
Network accessYesIn-process only
RETURNING clauseYesYes
Advisory locksYes --- safe multi-process migrationsNo
ILIKENativeEmulated via COLLATE NOCASE
UUID columnsNative gen_random_uuid()Text-based
JSONBNative with indexingJSON stored as text

Connection Pooling

Always configure the pool for your workload:

ts
let pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  max: 20,                      // Maximum connections in the pool
  idleTimeoutMillis: 30000,     // Close idle connections after 30s
  connectionTimeoutMillis: 2000, // Fail if a connection takes over 2s
})

Installation

bash
npm install remix pg
npm install -D @types/pg

Released under the MIT License.