Part 2: Setting Up Prisma with PostgreSQL

Introduction

In Part 1, we explored what ORMs are and why they matter. Now it's time to get our hands dirty. In this article, I'll walk you through setting up a TypeScript project with Prisma ORM and PostgreSQLβ€”the same setup I use for my production applications.

I remember spending an entire evening struggling with database connections and TypeScript configurations when I first started. This guide will save you that time by showing you the exact steps I now follow for every new project.

Prerequisites

Before we start, ensure you have these installed:

# Check Node.js version (I use v18 or higher)
node --version  # Should be v18.0.0 or higher

# Check npm version
npm --version

# Check PostgreSQL (we'll also cover Docker option)
psql --version

If you don't have PostgreSQL installed, don't worryβ€”I'll show you how to run it with Docker, which is what I use for local development.

Project Setup

Step 1: Initialize a TypeScript Project

Let me walk you through creating a new project from scratch:

Step 2: Configure TypeScript

Create a tsconfig.json file. This is the configuration I use for all my Node.js backend projects:

Step 3: Set Up PostgreSQL Database

I use Docker for local PostgreSQL because it keeps my machine clean and makes it easy to reset the database. Here's my docker-compose.yml:

Start the database:

Alternative: Using Local PostgreSQL

If you have PostgreSQL installed locally, create a database:

Initializing Prisma

Step 4: Initialize Prisma in Your Project

This command creates the Prisma directory and configuration files:

This creates two important files:

  1. prisma/schema.prisma - Your database schema definition

  2. .env - Environment variables (including database connection)

Step 5: Configure Database Connection

Open .env and update the database connection string:

Connection String Breakdown:

  • postgresql:// - Database type

  • postgres:postgres - Username:password

  • localhost:5432 - Host:port

  • prisma_tutorial - Database name

  • ?schema=public - PostgreSQL schema (default is public)

Step 6: Create Your First Schema

Open prisma/schema.prisma. This is where magic happens. Here's a real schema from one of my projects, simplified for learning:

Schema Breakdown:

  • generator client: Tells Prisma to generate TypeScript client code

  • datasource db: Defines PostgreSQL as our database

  • model User: Creates a users table (Prisma pluralizes by default)

  • @id: Marks primary key

  • @default(autoincrement()): Auto-incrementing integer

  • @unique: Ensures email uniqueness

  • @updatedAt: Automatically updates on record change

  • posts Post[]: One-to-many relationship

  • @relation(...): Defines foreign key constraint

Step 7: Create Your First Migration

Migrations track database schema changes over time. Here's how I create them:

You'll see output like:

Let's look at the generated SQL in prisma/migrations/20240204120000_init/migration.sql:

Creating Your First TypeScript File

Step 8: Set Up Prisma Client

Create src/index.ts:

Step 9: Add Scripts to package.json

Update your package.json:

Step 10: Run Your Application

You should see output like:

Exploring Your Database with Prisma Studio

Prisma Studio is a visual database browser. I use it constantly during development:

This opens http://localhost:5555 in your browser, where you can:

  • View all tables

  • Browse records

  • Edit data directly

  • Test queries

Common Issues I've Encountered

Issue 1: "Can't reach database server"

Solution:

Issue 2: "Environment variable not found: DATABASE_URL"

Make sure .env exists in your project root and is not in .gitignore for local development (but exclude it in production repos).

Issue 3: Port 5432 already in use

Project Structure

Here's how my project looks now:

Best Practices I Follow

  1. Always use migrations: Never modify the database directly in production

  2. Version control migrations: Commit migration files to Git

  3. Exclude .env from Git: Use .env.example for templates

  4. Use Prisma Studio: Great for debugging and exploring data

  5. Enable query logging: Helps understand what SQL is generated

  6. Handle disconnection: Always call prisma.$disconnect() in finally block

What's Next?

We now have a fully functional TypeScript + Prisma + PostgreSQL setup! In Part 3, we'll dive deeper into:

  • Schema design best practices

  • Defining complex relationships (one-to-many, many-to-many)

  • Data validation with Prisma

  • Migration strategies for evolving schemas

  • Indexing for performance

Conclusion

Setting up Prisma with TypeScript and PostgreSQL is straightforward once you know the steps. The combination of type safety from TypeScript and the developer experience from Prisma makes building database-backed applications enjoyable.

The setup we've created here is production-ready (with a few security additions we'll cover later). I use this exact stack for microservices handling thousands of requests per second.


This article is part of my personal knowledge sharing based on real projects I've built. The setup shown here is what I use in production with minor adjustments for secrets management.

Last updated