Configure Deno database connections to PostgreSQL and Redis with connection pooling

Intermediate 45 min Apr 08, 2026 859 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Set up production-ready database connections in Deno applications with PostgreSQL and Redis, including SSL configuration, connection pooling, authentication, and comprehensive error handling for high-performance TypeScript applications.

Prerequisites

  • Root or sudo access
  • PostgreSQL 12+ installed
  • Redis 6+ installed
  • Basic TypeScript knowledge

What this solves

Modern Deno applications require efficient database connections to handle production workloads. This tutorial configures PostgreSQL and Redis connections with connection pooling, SSL encryption, authentication, and proper error handling. You'll establish reliable database connectivity that scales with your application demands and maintains security standards for production deployments.

Step-by-step configuration

Install Deno runtime

First, install the latest version of Deno on your system if not already present.

curl -fsSL https://deno.land/install.sh | sh
echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
curl -fsSL https://deno.land/install.sh | sh
echo 'export PATH="$HOME/.deno/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

Install PostgreSQL and Redis servers

Install PostgreSQL and Redis database servers for local development and testing.

sudo apt update
sudo apt install -y postgresql postgresql-contrib redis-server
sudo dnf install -y postgresql postgresql-server postgresql-contrib redis
sudo postgresql-setup --initdb

Configure PostgreSQL authentication

Set up PostgreSQL with a dedicated database and user for your Deno application.

sudo systemctl enable --now postgresql
sudo -u postgres psql -c "CREATE USER denoapp WITH PASSWORD 'secure_db_password123';"
sudo -u postgres psql -c "CREATE DATABASE denoapp_db OWNER denoapp;"
sudo -u postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE denoapp_db TO denoapp;"

Configure Redis authentication

Enable Redis authentication and set a strong password for secure connections.

bind 127.0.0.1
requirepass redis_secure_password456
maxmemory 256mb
maxmemory-policy allkeys-lru
tcp-keepalive 300
sudo systemctl enable --now redis-server
sudo systemctl restart redis-server

Create project structure

Set up the basic Deno project structure with TypeScript configuration and database modules.

mkdir deno-db-app && cd deno-db-app
mkdir -p src/{config,database,models,utils}
touch src/main.ts src/config/database.ts src/database/postgresql.ts src/database/redis.ts

Configure database connection settings

Create centralized database configuration with environment variable support and connection pooling settings.

export interface DatabaseConfig {
  postgresql: {
    hostname: string;
    port: number;
    database: string;
    username: string;
    password: string;
    pool: {
      max: number;
      min: number;
      idle_timeout: number;
      connect_timeout: number;
    };
    ssl: {
      enabled: boolean;
      ca?: string;
      cert?: string;
      key?: string;
    };
  };
  redis: {
    hostname: string;
    port: number;
    password?: string;
    pool: {
      max: number;
      min: number;
      idle_timeout: number;
    };
    ssl: {
      enabled: boolean;
    };
    cluster: {
      enabled: boolean;
      nodes?: string[];
    };
  };
}

export const databaseConfig: DatabaseConfig = {
  postgresql: {
    hostname: Deno.env.get("PG_HOST") || "localhost",
    port: parseInt(Deno.env.get("PG_PORT") || "5432"),
    database: Deno.env.get("PG_DATABASE") || "denoapp_db",
    username: Deno.env.get("PG_USERNAME") || "denoapp",
    password: Deno.env.get("PG_PASSWORD") || "secure_db_password123",
    pool: {
      max: parseInt(Deno.env.get("PG_POOL_MAX") || "20"),
      min: parseInt(Deno.env.get("PG_POOL_MIN") || "5"),
      idle_timeout: parseInt(Deno.env.get("PG_POOL_IDLE_TIMEOUT") || "10000"),
      connect_timeout: parseInt(Deno.env.get("PG_CONNECT_TIMEOUT") || "5000"),
    },
    ssl: {
      enabled: Deno.env.get("PG_SSL_ENABLED") === "true",
      ca: Deno.env.get("PG_SSL_CA"),
      cert: Deno.env.get("PG_SSL_CERT"),
      key: Deno.env.get("PG_SSL_KEY"),
    },
  },
  redis: {
    hostname: Deno.env.get("REDIS_HOST") || "localhost",
    port: parseInt(Deno.env.get("REDIS_PORT") || "6379"),
    password: Deno.env.get("REDIS_PASSWORD") || "redis_secure_password456",
    pool: {
      max: parseInt(Deno.env.get("REDIS_POOL_MAX") || "10"),
      min: parseInt(Deno.env.get("REDIS_POOL_MIN") || "2"),
      idle_timeout: parseInt(Deno.env.get("REDIS_POOL_IDLE_TIMEOUT") || "30000"),
    },
    ssl: {
      enabled: Deno.env.get("REDIS_SSL_ENABLED") === "true",
    },
    cluster: {
      enabled: Deno.env.get("REDIS_CLUSTER_ENABLED") === "true",
      nodes: Deno.env.get("REDIS_CLUSTER_NODES")?.split(","),
    },
  },
};

Implement PostgreSQL connection manager

Create a PostgreSQL connection pool with SSL support, health checks, and proper error handling.

import { Pool, PoolClient } from "https://deno.land/x/postgres@v0.19.3/mod.ts";
import { databaseConfig } from "../config/database.ts";

export class PostgreSQLManager {
  private static instance: PostgreSQLManager;
  private pool: Pool;
  private isConnected = false;

  private constructor() {
    const config = databaseConfig.postgresql;
    
    this.pool = new Pool({
      hostname: config.hostname,
      port: config.port,
      database: config.database,
      user: config.username,
      password: config.password,
      connection: {
        attempts: 3,
        interval: 1000,
      },
      tls: config.ssl.enabled ? {
        enabled: true,
        enforce: false,
        caCertificates: config.ssl.ca ? [await Deno.readTextFile(config.ssl.ca)] : undefined,
      } : undefined,
    }, config.pool.max, true);

    this.setupEventHandlers();
  }

  public static getInstance(): PostgreSQLManager {
    if (!PostgreSQLManager.instance) {
      PostgreSQLManager.instance = new PostgreSQLManager();
    }
    return PostgreSQLManager.instance;
  }

  private setupEventHandlers(): void {
    this.pool.addEventListener("error", (event) => {
      console.error("PostgreSQL pool error:", event.error);
      this.isConnected = false;
    });

    this.pool.addEventListener("connect", () => {
      console.log("PostgreSQL connection established");
      this.isConnected = true;
    });

    this.pool.addEventListener("end", () => {
      console.log("PostgreSQL connection ended");
      this.isConnected = false;
    });
  }

  public async connect(): Promise

Implement Redis connection manager

Create a Redis connection pool with clustering support, authentication, and automatic reconnection.

import { connect, Redis } from "https://deno.land/x/redis@v0.32.3/mod.ts";
import { databaseConfig } from "../config/database.ts";

export class RedisManager {
  private static instance: RedisManager;
  private connections: Redis[] = [];
  private currentIndex = 0;
  private isConnected = false;
  private reconnectAttempts = 0;
  private maxReconnectAttempts = 5;

  private constructor() {
    this.setupConnectionPool();
  }

  public static getInstance(): RedisManager {
    if (!RedisManager.instance) {
      RedisManager.instance = new RedisManager();
    }
    return RedisManager.instance;
  }

  private async setupConnectionPool(): Promise

Create database initialization module

Implement a centralized database initialization and health monitoring system.

import { PostgreSQLManager } from "./postgresql.ts";
import { RedisManager } from "./redis.ts";

export class DatabaseManager {
  private static instance: DatabaseManager;
  private postgresql: PostgreSQLManager;
  private redis: RedisManager;
  private healthCheckInterval?: number;

  private constructor() {
    this.postgresql = PostgreSQLManager.getInstance();
    this.redis = RedisManager.getInstance();
  }

  public static getInstance(): DatabaseManager {
    if (!DatabaseManager.instance) {
      DatabaseManager.instance = new DatabaseManager();
    }
    return DatabaseManager.instance;
  }

  public async initialize(): Promise

Create example application

Build a sample Deno application demonstrating database connections, error handling, and connection pooling.

import { Application, Router } from "https://deno.land/x/oak@v16.1.0/mod.ts";
import { DatabaseManager } from "./database/index.ts";

const app = new Application();
const router = new Router();
const db = DatabaseManager.getInstance();

// Initialize database connections
try {
  await db.initialize();
} catch (error) {
  console.error("Failed to initialize databases:", error);
  Deno.exit(1);
}

// Health check endpoint
router.get("/health", async (ctx) => {
  try {
    const health = await db.runHealthChecks();
    const stats = db.getStats();
    
    ctx.response.body = {
      status: "ok",
      timestamp: new Date().toISOString(),
      databases: health,
      stats: stats,
    };
  } catch (error) {
    ctx.response.status = 500;
    ctx.response.body = {
      status: "error",
      message: error.message,
    };
  }
});

// PostgreSQL example endpoint
router.get("/users/:id", async (ctx) => {
  try {
    const userId = ctx.params.id;
    const postgresql = db.getPostgreSQL();
    
    // Example query with parameter binding
    const users = await postgresql.query(
      "SELECT id, username, email, created_at FROM users WHERE id = $1",
      [parseInt(userId)]
    );
    
    if (users.length === 0) {
      ctx.response.status = 404;
      ctx.response.body = { error: "User not found" };
      return;
    }
    
    ctx.response.body = {
      user: users[0],
      cached: false,
    };
  } catch (error) {
    console.error("Database query error:", error);
    ctx.response.status = 500;
    ctx.response.body = {
      error: "Internal server error",
      details: error.message,
    };
  }
});

// Redis caching example endpoint
router.get("/cache/:key", async (ctx) => {
  try {
    const key = ctx.params.key;
    const redis = db.getRedis();
    
    const value = await redis.get(`app:cache:${key}`);
    
    if (value) {
      ctx.response.body = {
        key: key,
        value: JSON.parse(value),
        cached: true,
        timestamp: new Date().toISOString(),
      };
    } else {
      ctx.response

Automated install script

Run this to automate the entire setup

Don't want to manage this yourself?

We handle infrastructure for businesses that depend on uptime. Fully managed, with one fixed contact who knows your setup.

You get one fixed contact who knows your setup

Rotterdam 04:06 · reachable in a message, no ticket form