How to Create Database Seed Scripts in Node.js
Database seeding is a crucial step in application development. It involves populating your database with initial or test data automatically, which helps during development, testing, and demos. For Node.js applications, seed scripts can be built to insert default or complex datasets consistently. Let’s explore how to build database seed scripts for a Node.js application using PostgreSQL.
1. What is Node.js and Data Seeding in a Node.js Application?
Node.js is an open-source, cross-platform JavaScript runtime environment built on Chrome’sV8 JavaScript engine. It enables developers to run JavaScript code outside the browser, making it a popular choice for backend development, APIs, and microservices. Node.js uses an event-driven, non-blocking I/O model, which makes it highly efficient and suitable for building scalable network applications.
In backend systems, data seeding refers to pre-populating a database with initial data. This is typically achieved by writing scripts in Node.js that insert default or sample records into the database. Data seeding is especially valuable for:
- Setting uptest environments with predictable datasets
- Providing default configurations for new installations
- Enabling rapid prototyping during early stages of development
- Creating demo versions of applications with realistic data
Data seeding in Node.js applications ensures that developers, testers, and CI/CD pipelines start with a consistent dataset every time, reducing environment-specific bugs and easing onboarding for new team members.
1.1 Setting up Node.js
To set up Node.js on Windows, download the installer fromhere. Run the installer, which includes the NPM package manager, and follow the setup wizard. After installation, you can verify Node.js and npm by running:
node -vnpm -v

2. Setting Up PostgreSQL
PostgreSQL is a powerful, open-source relational database system. To set it up locally:
- Download and install PostgreSQL from theofficial site.
- Create a new database and user for your Node.js application using
psqlor a GUI tool like pgAdmin. - Install the
pgnpm package in your Node.js project to connect to PostgreSQL.
2.1 Installing PostgreSQL Client for Node.js
npm install pg
3. Code Example
Here, we will set up the project, write scripts to insert sample data into theusers andorders tables, and demonstrate how to manage environment-specific seeding.
3.1 Setup
Before seeding data, set up a Node.js project:
mkdir pg-seed-examplecd pg-seed-examplenpm init -ynpm install pg
3.2 Seed Script
This script demonstrates how to create a PostgreSQL database, define schemas, and insert sample data using Node.js:
const { Pool } = require('pg');// PostgreSQL connection poolconst pool = new Pool({ user: 'your_db_user', host: 'localhost', database: 'your_db_name', password: 'your_db_password', port: 5432,});// Create tables if not existasync function createSchema() { await pool.query(` CREATE TABLE IF NOT EXISTS users ( id VARCHAR(50) PRIMARY KEY, name VARCHAR(100), email VARCHAR(100) UNIQUE, street VARCHAR(200), city VARCHAR(100), zip VARCHAR(20) ); `); await pool.query(` CREATE TABLE IF NOT EXISTS products ( id VARCHAR(50) PRIMARY KEY, name VARCHAR(100), price NUMERIC(10,2) ); `); await pool.query(` CREATE TABLE IF NOT EXISTS orders ( id VARCHAR(50) PRIMARY KEY, user_id VARCHAR(50) REFERENCES users(id) ); `); await pool.query(` CREATE TABLE IF NOT EXISTS order_items ( order_id VARCHAR(50) REFERENCES orders(id), product_id VARCHAR(50) REFERENCES products(id), quantity INT, PRIMARY KEY (order_id, product_id) ); `); console.log('Database schema created or verified.');}// Seed user dataasync function seedUsers() { const users = [ { id: 'user1', name: 'Alice', email: 'alice@example.com', street: '123 Elm St', city: 'Metropolis', zip: '12345' }, { id: 'user2', name: 'Bob', email: 'bob@example.com', street: '456 Oak St', city: 'Gotham', zip: '67890' }, ]; for (const user of users) { await pool.query( `INSERT INTO users(id, name, email, street, city, zip) VALUES($1,$2,$3,$4,$5,$6) ON CONFLICT (id) DO NOTHING`, [user.id, user.name, user.email, user.street, user.city, user.zip] ); console.log(\`Seeded user: \${user.name}\`); }}// Seed product dataasync function seedProducts() { const products = [ { id: 'prod1', name: 'Laptop', price: 1200 }, { id: 'prod2', name: 'Mouse', price: 20 }, { id: 'prod3', name: 'Keyboard', price: 50 }, ]; for (const product of products) { await pool.query( `INSERT INTO products(id, name, price) VALUES($1,$2,$3) ON CONFLICT (id) DO NOTHING`, [product.id, product.name, product.price] ); console.log(\`Seeded product: \${product.name}\`); }}// Seed order dataasync function seedOrders() { const orders = [ { id: 'order1', userId: 'user1' }, { id: 'order2', userId: 'user1' }, { id: 'order3', userId: 'user2' }, ]; for (const order of orders) { await pool.query( `INSERT INTO orders(id, user_id) VALUES($1,$2) ON CONFLICT (id) DO NOTHING`, [order.id, order.userId] ); console.log(\`Seeded order: \${order.id} for user \${order.userId}\`); }}// Seed order items (many-to-many relationship)async function seedOrderItems() { const orderItems = [ { orderId: 'order1', productId: 'prod1', quantity: 1 }, { orderId: 'order1', productId: 'prod2', quantity: 2 }, { orderId: 'order2', productId: 'prod2', quantity: 1 }, { orderId: 'order3', productId: 'prod3', quantity: 1 }, ]; for (const item of orderItems) { await pool.query( `INSERT INTO order_items(order_id, product_id, quantity) VALUES($1,$2,$3) ON CONFLICT (order_id, product_id) DO NOTHING`, [item.orderId, item.productId, item.quantity] ); console.log(\`Seeded order item: order \${item.orderId} -> product \${item.productId}\`); }}// Main seeding functionasync function seed() { if (process.env.NODE_ENV === 'development') { console.log('Running development seed...'); await createSchema(); await seedUsers(); await seedProducts(); await seedOrders(); await seedOrderItems(); } else { console.log('No seeding performed for environment:', process.env.NODE_ENV); } await pool.end();}seed() .then(() => { console.log('Seeding complete.'); process.exit(0); }) .catch((error) => { console.error('Seeding failed:', error); process.exit(1); });3.2.1 Code Explanation
This Node.js script connects to a PostgreSQL database using thepg module, creates required tables if they do not exist, and inserts sample data for development environments. ThecreateSchema function defines tables forusers,products,orders, andorder_items usingCREATE TABLE IF NOT EXISTS, ensuring proper primary and foreign key relationships to maintain data integrity, including a many-to-many link between orders and products. Separate seeding functions (seedUsers,seedProducts,seedOrders,seedOrderItems) insert predefined data using parameterizedINSERT queries withON CONFLICT clauses to avoid duplicate entries. Theseed function orchestrates schema creation and data insertion, executing only whenNODE_ENV is set to “development”, and finally closes the database connection pool, logging success or failure messages for tracking purposes.
3.3 package.json Scripts
Add a script topackage.json for running seeds:
{ "name": "pg-seed-example", "version": "1.0.0", "main": "seed.js", "scripts": { "seed:dev": "NODE_ENV=development node seed.js" }, "dependencies": { "pg": "^8.0.0" }}3.3.1 Code Explanation
Thispackage.json file defines a Node.js project named “pg-seed-example” with version 1.0.0 and a main entry point ofseed.js. It includes ascripts section with a custom scriptseed:dev that sets the environment variableNODE_ENV to “development” and runs the seed script. Thedependencies section listspg version 8.0.0 as the required package to enable PostgreSQL database connectivity from Node.js.
3.4 Running the Seed Script
Execute the seed script in development mode:
npm run seed:dev
This command sets the environment todevelopment and triggers theseed.js script, ensuring that seeding only happens in the intended environment.
3.5 Output
Upon successful execution, the console will show:
Running development seed...Database schema created or verified.Seeded user: AliceSeeded user: BobSeeded product: LaptopSeeded product: MouseSeeded product: KeyboardSeeded order: order1 for user user1Seeded order: order2 for user user1Seeded order: order3 for user user2Seeded order item: order order1 -> product prod1Seeded order item: order order1 -> product prod2Seeded order item: order order2 -> product prod2Seeded order item: order order3 -> product prod3Seeding complete.
This output shows that the script inserted users, products, orders, and the many-to-many relationships between orders and products without errors, confirming that the database seeding was successful and complete.
4. Unit Testing the Seed Script
Unit testing the seed script helps validate logic without interacting with a real database. By mocking database queries, we can simulate PostgreSQL responses and verify that the seed functions are executing correctly.
4.1 Benefits of Unit Testing Seed Scripts
- Prevent Data Corruption: Avoids modifying real or production databases during test runs.
- Verify Logic: Ensures seed functions insert the expected data and maintain correct relationships.
- Fast Feedback: Tests run quickly as they do not require a live database connection.
4.2 Example Unit Test using Jest
// seed.test.jsconst { seedUsers } = require('./seed'); // import function to testconst { Pool } = require('pg');// Mock the pg modulejest.mock('pg', () => { const mPool = { query: jest.fn(), end: jest.fn() }; return { Pool: jest.fn(() => mPool) };});describe('Seed Script Tests', () => { let pool; beforeAll(() => { pool = new Pool(); }); test('should insert users correctly', async () => { pool.query.mockResolvedValueOnce({}); // mock query result await seedUsers(); expect(pool.query).toHaveBeenCalled(); expect(pool.query).toHaveBeenCalledWith( expect.stringContaining('INSERT INTO users'), expect.any(Array) ); });});This Jest-based test suite mocks thepg module so that no real database connection is made. It intercepts calls topool.query and verifies that the correct SQL statement (anINSERT INTO command) is executed with the expected parameters. This ensures the seed function logic is correct, prevents accidental data modification, and provides fast, isolated feedback during development.
5. Documenting Seeding Practices
Maintain clear documentation to facilitate onboarding, collaboration, and consistency:
- Purpose and Scope: Explain why seeding is needed and which tables are seeded.
- Seed Data Structure: Describe data models, relationships, and default values.
- How to Run Seeds: Include commands, environment variables, and expected output.
- Environment Considerations: Specify which environments support seeding.
- Updating Seed Data: Outline procedures for modifying seed data over time.
- Dependencies and Tools: List required Node.js packages like
pg. - Known Issues and Limitations: Note any constraints such as performance considerations.
6. Conclusion
Database seeding is a vital practice in Node.js application development that ensures your PostgreSQL database is consistently populated with necessary initial or test data. Automating this process with seed scripts enables rapid setup of development and test environments, reliable demos, and reduced environment-specific bugs. By integrating seeding into your workflow, writing unit tests, and documenting your practices, your team can maintain stable, predictable, and maintainable application data efficiently.

Thank you!
We will contact you soon.



