Data persistence uses PostgreSQL. Raw SQL builds fluency for interviews and debugging; Knex adds migrations, seeds, and a query builder your Express services call. Learn both: SQL shows what the database actually runs; Knex shows how the app stays maintainable.

Migrations / seeds

Knex configuration ties together the database connection, migration folder, and seed scripts. Set this up once per project; every service then imports the shared knex instance.

2 topic(s) on this page.

How to configure Knex — Basic

Set up knexfile and database connection settings for PostgreSQL or other drivers.
Learn: Knex needs a knexfile describing the client (pg), connection string, and migration directory. The same config is used for queries, migrations, and seeds.

Supplementary examples

knexfile.js excerpt

module.exports = {
  development: {
    client: "pg",
    connection: process.env.DATABASE_URL,
    migrations: { directory: "./db/migrations" },
    seeds: { directory: "./db/seeds" },
  },
};

Shared connection module

const knex = require("knex");
const config = require("../knexfile");

module.exports = knex(config[process.env.NODE_ENV || "development"]);

Course example

// Update with your config settings
module.exports = {
development: {
client: "sqlite3",
connection: {
filename: "./dev.sqlite3",
},
},
test: {
client: "postgresql",
pool: { min: 1, max: 5 },
connection: {
database: "db_test",
user: "username_test",
password: "password_test",
},
},
staging: {
client: "postgresql",
connection: {
database: "db_staging",
user: "username_staging",
password: "password_staging",
},
pool: {
min: 2,
max: 10,
},
migrations: {
tableName: "knex_migrations",
},
},
production: {
client: "postgresql",
connection: {
database: "db_production",
user: "username_production",
password: "password_production",
},
pool: {
min: 2,
max: 10,
},
migrations: {
tableName: "knex_migrations",
},
},
};

Additional references & examples

How to seed data with Knex — Basic

Populate tables with initial or test data using Knex seed scripts.
Learn: Seeds load repeatable test or demo data after migrations. Keep seeds idempotent where possible (delete then insert, or use upsert patterns) so `knex seed:run` is safe locally.

Supplementary examples

Seed function

exports.seed = async function (knex) {
  await knex("users").del();
  await knex("users").insert([
    { username: "demo" },
    { username: "tester" },
  ]);
};

Course example

exports.seed = function (knex) {
// Deletes ALL existing entries
return knex("table_name")
.del()
.then(function () {
// Inserts seed entries
return knex("table_name").insert([
{ id: 1, colName: "rowValue1" },
{ id: 2, colName: "rowValue2" },
{ id: 3, colName: "rowValue3" },
]);
});
};

Additional references & examples