LangChain Tutorial (TypeScript): connecting to PostgreSQL for beginners

By Cyprian AaronsUpdated 2026-04-21
langchainconnecting-to-postgresql-for-beginnerstypescript

This tutorial shows you how to connect a TypeScript LangChain app to PostgreSQL, store data in a table, and query it back with SQL. You need this when your agent has to persist chat history, keep structured business data, or read from an existing Postgres database instead of relying on in-memory state.

What You'll Need

  • Node.js 18+
  • A PostgreSQL database you can connect to locally or remotely
  • A .env file for connection settings
  • These packages:
    • langchain
    • @langchain/openai
    • pg
    • dotenv
    • typescript
    • tsx or ts-node
  • An OpenAI API key set as OPENAI_API_KEY
  • A PostgreSQL connection string set as DATABASE_URL

Install the dependencies:

npm install langchain @langchain/openai pg dotenv
npm install -D typescript tsx @types/node @types/pg

Step-by-Step

  1. Create a simple project setup and load your environment variables. Keep the Postgres URL outside your code so you can move between local dev and production without editing source files.
import "dotenv/config";

const requiredEnvVars = ["OPENAI_API_KEY", "DATABASE_URL"] as const;

for (const key of requiredEnvVars) {
  if (!process.env[key]) {
    throw new Error(`Missing required environment variable: ${key}`);
  }
}

console.log("Environment loaded");
  1. Create a Postgres connection pool. LangChain can work with any SQL database through a standard driver, and pg is the normal choice for PostgreSQL in Node.js.
import { Pool } from "pg";
import "dotenv/config";

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

async function main() {
  const result = await pool.query("SELECT NOW() AS now");
  console.log(result.rows[0]);
  await pool.end();
}

main().catch(async (err) => {
  console.error(err);
  await pool.end();
  process.exit(1);
});
  1. Create a table and insert a few rows. This gives LangChain something real to query, which is better than testing against empty tables or mock data.
import { Pool } from "pg";
import "dotenv/config";

const pool = new Pool({ connectionString: process.env.DATABASE_URL });

async function main() {
  await pool.query(`
    CREATE TABLE IF NOT EXISTS support_tickets (
      id SERIAL PRIMARY KEY,
      customer_name TEXT NOT NULL,
      status TEXT NOT NULL,
      priority INT NOT NULL,
      created_at TIMESTAMP DEFAULT NOW()
    )
  `);

  await pool.query(
    `INSERT INTO support_tickets (customer_name, status, priority)
     VALUES ($1, $2, $3), ($4, $5, $6)
     ON CONFLICT DO NOTHING`,
    ["Alice", "open", 1, "Bob", "closed", 3]
  );

  console.log("Table ready");
  await pool.end();
}

main().catch(async (err) => {
  console.error(err);
  await pool.end();
  process.exit(1);
});
  1. Wire LangChain to an SQL tool using PostgreSQL. The cleanest beginner path is to let LangChain generate SQL against your database schema, then execute the query through the built-in SQL toolkit.
import "dotenv/config";
import { Pool } from "pg";
import { DataSource } from "typeorm";
import { SqlDatabase } from "@langchain/sql_db";
import { createSqlQueryChain } from "langchain/chains/sql_db";
import { ChatOpenAI } from "@langchain/openai";

async function main() {
  const pool = new Pool({ connectionString: process.env.DATABASE_URL });

  const dataSource = new DataSource({
    type: "postgres",
    url: process.env.DATABASE_URL,
    entities: [],
    synchronize: false,
    logging: false,
  });

  await dataSource.initialize();

  const db = await SqlDatabase.fromDataSourceParams({
    appDataSource: dataSource,
    includesTables: ["support_tickets"],
  });

  const llm = new ChatOpenAI({ model: "gpt-4o-mini", temperature: zero });
}

main().catch(console.error);
  1. Fix the chain call and run a natural-language question against Postgres. This is where the agent becomes useful: you ask for business answers in plain English and let LangChain translate that into SQL.
import "dotenv/config";
import { DataSource } from "typeorm";
import { SqlDatabase } from "@langchain/sql_db";
import { createSqlQueryChain } from "langchain/chains/sql_db";
import { ChatOpenAI } from "@langchain/openai";

async function main() {
  const dataSource = new DataSource({
    type: "postgres",
    url: process.env.DATABASE_URL,
    entities: [],
    synchronize: false,
    logging: false,
  });

  await dataSource.initialize();

  const db = await SqlDatabase.fromDataSourceParams({
    appDataSource: dataSource,
    includesTables: ["support_tickets"],
  });

  const llm = new ChatOpenAI({ model: "gpt-4o-mini", temperature: 0 });
  const chain = createSqlQueryChain({ llm, db });

	const question = "How many open support tickets are there?";
	const result = await chain.invoke({ question });

	console.log(result);

	await dataSource.destroy();
}

main().catch(console.error);

Testing It

Run each script once to confirm your environment variables are correct, then check that the table creation and inserts complete without errors. After that, ask a few different questions like “Which ticket has the highest priority?” or “How many closed tickets do we have?” and confirm the generated SQL matches what you expect.

If the chain returns nonsense, inspect the schema visibility first. In most beginner setups, the issue is one of these:

  • The table name was not included in includesTables
  • The database user lacks permission to read the table
  • The model does not have enough schema context because the table is empty or poorly named

A good smoke test is to run this directly against Postgres before involving LangChain:

SELECT status, COUNT(*) 
FROM support_tickets
GROUP BY status;

If that works and LangChain does not, the problem is in your chain configuration, not your database.

Next Steps

  • Add read-only guards so generated SQL cannot write or drop tables
  • Wrap this in an agent with tools for ticket lookup and customer lookup
  • Learn how to expose only specific schemas instead of the whole database

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides