@agentuity/postgres
⚠️ DEPRECATED — Use pg or drizzle-orm/node-postgres directly against your DATABASE_URL.
This package is no longer recommended for new projects.
Resilient PostgreSQL client with automatic reconnection for Agentuity projects.
Features
- 🔄 Automatic Reconnection - Exponential backoff with jitter
- 🏷️ Tagged Template Literals - Clean, SQL-injection-safe queries
- 💼 Transaction Support - Full transaction and savepoint support
- 📊 Connection Stats - Track connection health and reconnection history
- 🔌 Bun Native - Wraps Bun's high-performance SQL driver
Installation
bun add @agentuity/postgres
Quick Start
import { postgres } from '@agentuity/postgres';
const sql = postgres();
const users = await sql`SELECT * FROM users WHERE active = ${true}`;
const userId = 123;
const user = await sql`SELECT * FROM users WHERE id = ${userId}`;
await sql.close();
Configuration
import { postgres } from '@agentuity/postgres';
const sql = postgres({
url: 'postgres://user:pass@localhost:5432/mydb',
hostname: 'localhost',
port: 5432,
username: 'user',
password: 'pass',
database: 'mydb',
max: 10,
idleTimeout: 30,
connectionTimeout: 30,
tls: true,
reconnect: {
enabled: true,
maxAttempts: 10,
initialDelayMs: 100,
maxDelayMs: 30000,
multiplier: 2,
jitterMs: 1000,
},
onclose: (error) => console.log('Connection closed', error),
onreconnect: (attempt) => console.log(`Reconnecting... attempt ${attempt}`),
onreconnected: () => console.log('Reconnected!'),
onreconnectfailed: (error) => console.error('Reconnection failed', error),
});
Transactions
const tx = await sql.begin();
try {
await tx`INSERT INTO users (name, email) VALUES (${name}, ${email})`;
await tx`UPDATE accounts SET balance = balance - ${amount} WHERE id = ${fromId}`;
await tx`UPDATE accounts SET balance = balance + ${amount} WHERE id = ${toId}`;
await tx.commit();
} catch (error) {
await tx.rollback();
throw error;
}
Transaction Options
const tx = await sql.begin({
isolationLevel: 'serializable',
readOnly: true,
deferrable: true,
});
Savepoints
const tx = await sql.begin();
await tx`INSERT INTO users (name) VALUES ('Alice')`;
const savepoint = await tx.savepoint();
await tx`INSERT INTO users (name) VALUES ('Bob')`;
await savepoint.rollback();
await tx.commit();
Graceful Shutdown
The client automatically detects application shutdown signals (SIGTERM, SIGINT) and prevents reconnection attempts during shutdown:
process.on('SIGTERM', async () => {
sql.shutdown();
await sql.close();
process.exit(0);
});
Waiting for Connection
If you need to ensure the connection is established before proceeding:
await sql.waitForConnection();
await sql.waitForConnection(5000);
Connection Stats
const stats = sql.stats;
console.log({
connected: stats.connected,
reconnecting: stats.reconnecting,
totalConnections: stats.totalConnections,
reconnectAttempts: stats.reconnectAttempts,
failedReconnects: stats.failedReconnects,
lastConnectedAt: stats.lastConnectedAt,
lastDisconnectedAt: stats.lastDisconnectedAt,
});
Error Handling
import {
postgres,
ConnectionClosedError,
ReconnectFailedError,
TransactionError,
isRetryableError,
} from '@agentuity/postgres';
try {
const result = await sql`SELECT * FROM users`;
} catch (error) {
if (error instanceof ConnectionClosedError) {
console.log('Connection closed, waiting for reconnect...');
}
if (error instanceof ReconnectFailedError) {
console.error(`Failed after ${error.attempts} attempts`);
}
if (error instanceof TransactionError) {
console.error(`Transaction ${error.phase} failed`);
}
if (isRetryableError(error)) {
}
}
Raw SQL Access
For advanced use cases, you can execute unparameterized queries:
const result = await sql.unsafe('SELECT * FROM users WHERE id = 1');
const rawSql = sql.raw;
API Reference
postgres(config?)
Creates a new PostgreSQL client.
config - Connection URL string or configuration object
- Returns:
CallablePostgresClient
PostgresClient
The main client class with the following methods:
query(strings, ...values) - Execute a parameterized query
begin(options?) - Start a transaction
close() - Close all connections
shutdown() - Signal shutdown (prevents reconnection)
waitForConnection(timeoutMs?) - Wait for connection to be established
unsafe(query) - Execute an unparameterized query
Properties:
connected - Whether currently connected
reconnecting - Whether reconnection is in progress
shuttingDown - Whether shutdown has been signaled
stats - Connection statistics
raw - Underlying Bun.SQL instance
Transaction
Returned by begin():
query(strings, ...values) - Execute query in transaction
savepoint(name?) - Create a savepoint
commit() - Commit the transaction
rollback() - Rollback the transaction
Savepoint
Returned by transaction.savepoint():
rollback() - Rollback to this savepoint
release() - Release the savepoint
Global Registry and Shutdown
All PostgreSQL clients are automatically registered in a global registry. Wire shutdownAll() into your process's shutdown signals so clients close cleanly:
import { shutdownAll, getClientCount } from '@agentuity/postgres';
console.log(`Active clients: ${getClientCount()}`);
process.on('SIGTERM', async () => {
await shutdownAll(5000);
process.exit(0);
});
License
Apache-2.0