Module 3: Databases with JavaScript
SQL Concepts: Tables, Keys & Joins
A SQL (relational) database stores data in tables — rows and columns, like a structured spreadsheet:
users table
| id | name | email |
|----|-------|-------------------|
| 1 | Chiru | chiru@example.com |
posts table
| id | user_id | title |
|----|---------|-------------|
| 1 | 1 | "Hello" |
- Primary key — a column that uniquely identifies each row (
idabove) - Foreign key — a column referencing another table's primary key
(
user_idabove links a post to its user) - Join — combines rows from multiple tables based on a related key
SELECT users.name, posts.title
FROM posts
JOIN users ON posts.user_id = users.id;
CRUD is short for Create, Read, Update, Delete — the four basic operations any database-backed app performs, mapping naturally onto REST's POST/GET/PUT/DELETE from the previous chapter. A transaction groups several operations so they all succeed together or all fail together, keeping data consistent.
PostgreSQL, MySQL & SQLite
PostgreSQL and MySQL are full server-based relational databases, commonly used in production for real applications. SQLite stores an entire database in a single file with no separate server process — great for local development, small apps, and mobile/desktop apps.
NoSQL: MongoDB & Redis
MongoDB stores data as flexible JSON-like documents instead of rigid rows and columns — a natural fit for JavaScript, since documents look just like JS objects:
{
"_id": "abc123",
"name": "Chiru",
"posts": [{ "title": "Hello" }, { "title": "World" }]
}
Redis is an extremely fast in-memory key-value store — used for caching, sessions, rate limiting counters, and real-time leaderboards, rather than as a primary database.
Prisma, Drizzle & Mongoose
An ORM (Object-Relational Mapper) lets you work with a database using JavaScript objects and methods instead of writing raw SQL by hand:
// Prisma — define the schema, then query with a fully-typed client
// schema.prisma
model User {
id Int @id @default(autoincrement())
name String
email String @unique
}
// Using the generated Prisma Client in JavaScript/TypeScript
const user = await prisma.user.create({
data: { name: "Chiru", email: "chiru@example.com" }
});
const users = await prisma.user.findMany({ where: { name: "Chiru" } });
Drizzle is a lighter, more SQL-like alternative to Prisma. Mongoose is the equivalent tool for MongoDB, defining schemas and models for document data:
const User = mongoose.model("User", { name: String, email: String });
const user = await User.create({ name: "Chiru", email: "chiru@example.com" });
Frontend → API → Database Flow
Frontend (React, or plain JS)
↓ fetch("/api/users")
Backend API (Express/Fastify/NestJS)
↓ prisma.user.findMany()
Database (PostgreSQL/MongoDB/etc.)
↑ rows/documents returned
Backend
↑ res.json(users)
Frontend
↑ renders the data on screen
This request-response cycle — frontend asks, backend fetches from the database and responds, frontend renders — is the backbone of virtually every full-stack JavaScript application.