Skip to main content
Node.js & Express·Lesson 4 of 5

Working with Databases

Most web applications need to store data persistently. In this lesson, you will learn how to connect an Express application to both SQL and NoSQL databases and perform create, read, update, and delete (CRUD) operations.

Choosing a Database

TypeExamplesBest For
SQLPostgreSQL, MySQLStructured data, complex queries, relationships
NoSQLMongoDB, RedisFlexible schemas, rapid prototyping
In-memoryRedis, SQLiteCaching, sessions, quick prototypes

For production applications, PostgreSQL is an excellent default choice. MongoDB is popular for projects where schema flexibility matters.

SQLite for Development

SQLite is a file-based database perfect for development and prototyping. Install the better-sqlite3 driver:

npm install better-sqlite3
Ctrl+Enter
HTML
CSS
JS
Preview

Integrating with Express

Create a data access layer that your routes can use:

Ctrl+Enter
HTML
CSS
JS
Preview
Ctrl+Enter
HTML
CSS
JS
Preview

MongoDB with Mongoose

For NoSQL, MongoDB with Mongoose is a popular combination:

npm install mongoose

Connecting

Ctrl+Enter
HTML
CSS
JS
Preview

Defining a Schema

Ctrl+Enter
HTML
CSS
JS
Preview

CRUD with Mongoose

Ctrl+Enter
HTML
CSS
JS
Preview

Database Transactions

Transactions ensure that multiple operations either all succeed or all fail:

Ctrl+Enter
HTML
CSS
JS
Preview

Database Migrations

As your schema evolves, use migrations to track changes:

Ctrl+Enter
HTML
CSS
JS
Preview

For production, use a migration tool like knex, prisma migrate, or sequelize-cli.

Practical Exercise

Build a complete bookstore API with database integration:

Ctrl+Enter
HTML
CSS
JS
Preview

Key Takeaways

  • Choose SQL for structured data with relationships; choose NoSQL for flexible schemas.
  • SQLite is excellent for development and prototyping — no server setup required.
  • Always validate input before writing to the database and handle constraint errors gracefully.
  • Use transactions when multiple operations must succeed or fail together.
  • Separate your database logic from your route handlers for cleaner, testable code.