Step 8 of 12 67% complete

Step 8: Database Setup with Migrations

What You'll Learn

  • Configure SQLite database connection using proper.json
  • Create database migrations with the Proper CLI
  • Write up and down migration files
  • Run and rollback migrations
  • Understand migration best practices

What You'll Build

A SQLite database with version-controlled migrations for your todos table.

Why Migrations?

Database migrations let you version control your database schema. Instead of manually running SQL commands, you create migration files that can be applied and rolled back consistently across environments. This means:

  • Team collaboration: Everyone has the same database structure
  • Deployment safety: Changes are applied in order, every time
  • Rollback capability: Undo changes if something goes wrong
  • History tracking: See when and what changed in your schema

Project Files Overview

Here's an overview of the database configuration and migration files you'll create. Click on files in the tree to explore. Files marked with NEW are the ones you'll create.

my-noego-app
proper.json NEW
database
migrations
1
2
3
4
5
{
  "database": "sqlite",
  "sqlite": { "database": "database/db.sqlite" },
  "migration_folder": "migrations"
}

Configuring SQLite

Create a proper.json configuration file in your project root:

proper.json
1
2
3
4
5
{
  "database": "sqlite",
  "sqlite": { "database": "database/db.sqlite" },
  "migration_folder": "migrations"
}

This tells Proper:

  • database - Which database driver to use (sqlite)
  • sqlite.database - Path to the SQLite database file
  • migration_folder - Where migration files are stored

Creating Your First Migration

First, create the database directory, then generate a migration:

terminal
1
2
mkdir -p database
npx proper create create_todos_table

This creates two files in your migrations/ folder:

  • YYYYMMDDHHMMSS-create_todos_table.up.sql - Applied when migrating up
  • YYYYMMDDHHMMSS-create_todos_table.down.sql - Applied when rolling back

Writing the Up Migration

The up migration creates your table:

migrations/YYYYMMDDHHMMSS-create_todos_table.up.sql
1
2
3
4
5
6
7
CREATE TABLE todos (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title TEXT NOT NULL,
    description TEXT,
    completed INTEGER NOT NULL DEFAULT 0,
    created_at TEXT NOT NULL DEFAULT (datetime('now'))
);

Key SQLite patterns:

  • INTEGER PRIMARY KEY AUTOINCREMENT - Auto-incrementing ID
  • TEXT NOT NULL - Required string field
  • INTEGER DEFAULT 0 - Boolean stored as 0/1
  • datetime('now') - SQLite function for current timestamp

Writing the Down Migration

The down migration reverses the up migration:

migrations/YYYYMMDDHHMMSS-create_todos_table.down.sql
1
DROP TABLE IF EXISTS todos;

Always use IF EXISTS to avoid errors when the table doesn't exist.

Running Migrations

Apply all pending migrations:

terminal
1
npx proper up

Rollback the last migration:

terminal
1
npx proper down

Check migration status:

terminal
1
npx proper status

Migration Best Practices

  • One change per migration: Keep migrations focused and atomic
  • Always write down migrations: Every up needs a reversible down
  • Never edit applied migrations: Create new migrations for changes
  • Use descriptive names: Name migrations after what they do
  • Test rollbacks: Verify your down migrations work correctly

What's Next?

With our database set up and migrations in place, our backend is complete! In the next step, we'll build a frontend to interact with our API.

Troubleshooting

NoEgo

© 2025 NoEgo. All rights reserved.