<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Hussen Ghadban</title>
    <description>The latest articles on DEV Community by Hussen Ghadban (@hussen_ghadban_41bd747c70).</description>
    <link>https://dev.to/hussen_ghadban_41bd747c70</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1976826%2F80028a25-e7bf-4e25-b41f-e940a9bc42e4.jpg</url>
      <title>DEV Community: Hussen Ghadban</title>
      <link>https://dev.to/hussen_ghadban_41bd747c70</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hussen_ghadban_41bd747c70"/>
    <language>en</language>
    <item>
      <title>PostgreSQL vs MongoDB: A Developer's Comparison with Node.js &amp; Express</title>
      <dc:creator>Hussen Ghadban</dc:creator>
      <pubDate>Tue, 22 Jul 2025 13:56:11 +0000</pubDate>
      <link>https://dev.to/hussen_ghadban_41bd747c70/postgresql-vs-mongodb-a-developers-comparison-with-nodejs-express-b9f</link>
      <guid>https://dev.to/hussen_ghadban_41bd747c70/postgresql-vs-mongodb-a-developers-comparison-with-nodejs-express-b9f</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6zgmuscm45a409s24igv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6zgmuscm45a409s24igv.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When building modern web applications, choosing the right database is crucial for your project's success. Today, we'll dive deep into two popular database solutions: &lt;strong&gt;PostgreSQL with Prisma and MongoDB with Mongoose&lt;/strong&gt;, both integrated with Node.js and Express.js.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is PostgreSQL?&lt;/strong&gt;&lt;br&gt;
PostgreSQL is a powerful, open-source relational database management system (RDBMS) that has been around since 1986. It's known for its reliability, feature robustness, and performance. PostgreSQL uses structured query language (SQL) and follows ACID properties, making it perfect for applications that require complex relationships, transactions, and data integrity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is MongoDB?&lt;/strong&gt;&lt;br&gt;
MongoDB is a NoSQL document database that stores data in flexible, JSON-like documents called BSON. It's designed for scalability and flexibility, allowing developers to work with data in a more natural way for many applications. MongoDB is schema-less, meaning you can add fields to documents without having to modify the entire collection structure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting Up the Project&lt;/strong&gt;&lt;br&gt;
Let's create a practical example using a Product model to demonstrate the differences between these two approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;PostgreSQL with Prisma Setup&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Schema Definition
With Prisma, you define your database schema in a schema.prisma file:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

model Product {
  id          String   @id @default(cuid())
  name        String
  description String?
  price       Float
  category    String
  stock       Int
  tags        String[]
  specifications Json?
  createdAt   DateTime @default(now())
  updatedAt   DateTime @updatedAt

  @@map("products")
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;2. Migration Process&lt;/strong&gt;&lt;br&gt;
Important: After defining your schema, you need to run migrations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Generate and apply the migration
npx prisma migrate dev --name init

# Generate the Prisma client
npx prisma generate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates the actual database tables and generates the type-safe client.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Prisma Client Setup&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { PrismaClient } = require('@prisma/client');

const prisma = new PrismaClient();

module.exports = prisma;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;MongoDB with Mongoose Setup&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;1. Schema Definition&lt;/strong&gt;&lt;br&gt;
With Mongoose, you define schemas using JavaScript:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require('mongoose');

const productSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true,
    trim: true
  },
  description: {
    type: String,
    trim: true
  },
  price: {
    type: Number,
    required: true,
    min: 0
  },
  category: {
    type: String,
    required: true
  },
  stock: {
    type: Number,
    required: true,
    min: 0
  },
  tags: [String],
  specifications: {
    type: Map,
    of: mongoose.Schema.Types.Mixed
  }
}, {
  timestamps: true // Automatically adds createdAt and updatedAt
});

module.exports = mongoose.model('Product', productSchema);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Database Connection&lt;/strong&gt;&lt;br&gt;
No Migration Needed: MongoDB automatically creates collections when you first insert data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const mongoose = require('mongoose');

const connectDB = async () =&amp;gt; {
  try {
    await mongoose.connect(process.env.MONGODB_URI);
    console.log('MongoDB connected successfully');
  } catch (error) {
    console.error('MongoDB connection error:', error);
    process.exit(1);
  }
};

module.exports = connectDB;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;CRUD Operations Comparison&lt;/strong&gt;&lt;br&gt;
Let's see how basic operations differ between the two approaches:&lt;br&gt;
&lt;strong&gt;Creating Products&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;PostgreSQL + Prisma:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const prisma = require('../lib/prisma');

// Create a new product
app.post('/api/products', async (req, res) =&amp;gt; {
  try {
    const product = await prisma.product.create({
      data: {
        name: req.body.name,
        description: req.body.description,
        price: req.body.price,
        category: req.body.category,
        stock: req.body.stock,
        tags: req.body.tags,
        specifications: req.body.specifications
      }
    });

    res.status(201).json(product);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;MongoDB + Mongoose:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const Product = require('../models/Product');

// Create a new product
app.post('/api/products', async (req, res) =&amp;gt; {
  try {
    const product = new Product({
      name: req.body.name,
      description: req.body.description,
      price: req.body.price,
      category: req.body.category,
      stock: req.body.stock,
      tags: req.body.tags,
      specifications: req.body.specifications
    });

    const savedProduct = await product.save();
    res.status(201).json(savedProduct);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Fetching Products&lt;br&gt;
PostgreSQL + Prisma:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Get all products with filtering and pagination
app.get('/api/products', async (req, res) =&amp;gt; {
  try {
    const { category, minPrice, maxPrice, page = 1, limit = 10 } = req.query;

    const where = {};
    if (category) where.category = category;
    if (minPrice || maxPrice) {
      where.price = {};
      if (minPrice) where.price.gte = parseFloat(minPrice);
      if (maxPrice) where.price.lte = parseFloat(maxPrice);
    }

    const products = await prisma.product.findMany({
      where,
      skip: (page - 1) * limit,
      take: parseInt(limit),
      orderBy: { createdAt: 'desc' }
    });

    const totalCount = await prisma.product.count({ where });

    res.json({
      products,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total: totalCount,
        pages: Math.ceil(totalCount / limit)
      }
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get single product by ID
app.get('/api/products/:id', async (req, res) =&amp;gt; {
  try {
    const product = await prisma.product.findUnique({
      where: { id: req.params.id }
    });

    if (!product) {
      return res.status(404).json({ error: 'Product not found' });
    }

    res.json(product);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;MongoDB + Mongoose:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Get all products with filtering and pagination
app.get('/api/products', async (req, res) =&amp;gt; {
  try {
    const { category, minPrice, maxPrice, page = 1, limit = 10 } = req.query;

    const filter = {};
    if (category) filter.category = category;
    if (minPrice || maxPrice) {
      filter.price = {};
      if (minPrice) filter.price.$gte = parseFloat(minPrice);
      if (maxPrice) filter.price.$lte = parseFloat(maxPrice);
    }

    const products = await Product
      .find(filter)
      .limit(limit * 1)
      .skip((page - 1) * limit)
      .sort({ createdAt: -1 });

    const totalCount = await Product.countDocuments(filter);

    res.json({
      products,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total: totalCount,
        pages: Math.ceil(totalCount / limit)
      }
    });
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// Get single product by ID
app.get('/api/products/:id', async (req, res) =&amp;gt; {
  try {
    const product = await Product.findById(req.params.id);

    if (!product) {
      return res.status(404).json({ error: 'Product not found' });
    }

    res.json(product);
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Updating Products&lt;br&gt;
PostgreSQL + Prisma:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.put('/api/products/:id', async (req, res) =&amp;gt; {
  try {
    const product = await prisma.product.update({
      where: { id: req.params.id },
      data: {
        name: req.body.name,
        description: req.body.description,
        price: req.body.price,
        category: req.body.category,
        stock: req.body.stock,
        tags: req.body.tags,
        specifications: req.body.specifications
      }
    });

    res.json(product);
  } catch (error) {
    if (error.code === 'P2025') {
      return res.status(404).json({ error: 'Product not found' });
    }
    res.status(400).json({ error: error.message });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;MongoDB + Mongoose:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app.put('/api/products/:id', async (req, res) =&amp;gt; {
  try {
    const product = await Product.findByIdAndUpdate(
      req.params.id,
      {
        name: req.body.name,
        description: req.body.description,
        price: req.body.price,
        category: req.body.category,
        stock: req.body.stock,
        tags: req.body.tags,
        specifications: req.body.specifications
      },
      { new: true, runValidators: true }
    );

    if (!product) {
      return res.status(404).json({ error: 'Product not found' });
    }

    res.json(product);
  } catch (error) {
    res.status(400).json({ error: error.message });
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key Differences Explained&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Data Types&lt;br&gt;
PostgreSQL + Prisma&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model Product {
  id     String   @id @default(cuid())
  price  Float
  tags   String[]  // Array of strings
  data   Json?     // JSON field
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;MongoDB + Mongoose:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const schema = new mongoose.Schema({
  _id: mongoose.Schema.Types.ObjectId,
  price: Number,
  tags: [String],
  data: mongoose.Schema.Types.Mixed
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;When to Choose Which?&lt;br&gt;
Choose PostgreSQL + Prisma when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need ACID transactions&lt;/li&gt;
&lt;li&gt;Complex relationships between data&lt;/li&gt;
&lt;li&gt;Strong consistency is crucial&lt;/li&gt;
&lt;li&gt;You want type safety and compile-time checks&lt;/li&gt;
&lt;li&gt;Your team is familiar with SQL&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Choose MongoDB + Mongoose when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Rapid prototyping and iteration&lt;/li&gt;
&lt;li&gt;Flexible, evolving data structures&lt;/li&gt;
&lt;li&gt;Horizontal scaling requirements&lt;/li&gt;
&lt;li&gt;Document-based data fits naturally&lt;/li&gt;
&lt;li&gt;You need high write performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Both PostgreSQL with Prisma and MongoDB with Mongoose are excellent choices for Node.js applications, but they serve different needs. PostgreSQL excels in structured data scenarios requiring strong consistency and complex queries, while MongoDB shines in flexible, document-based applications that need rapid development and scaling.&lt;br&gt;
The choice ultimately depends on your specific use case, team expertise, and long-term scalability requirements. Consider starting with the technology that best matches your current needs while keeping future requirements in mind.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What's your experience with these databases? Share your thoughts in the comments below!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>mongodb</category>
      <category>database</category>
    </item>
  </channel>
</rss>
