Last Week

Week 22 was all about getting the backend under control. I spent a significant amount of time squashing bugs that I didn’t even realize existed in the app. It’s amazing how many issues surface when you start looking closely! But the most important accomplishment was finally implementing version control for my backend infrastructure, specifically the Supabase edge functions and the Postgres database with all its associated schemas, triggers, functions, and constraints.

This was something I’d been hesitating to tackle because, unlike frontend code, databases can’t be version controlled in a simple declarative way. I’d been “raw dogging” it up until now - just issuing SQL commands directly in the console whenever I needed to make database changes. But as I’m approaching alpha testing, I realized I need proper rollback capabilities and regression prevention.

What does it mean in English?

Think of version control like having a time machine for your code. When you’re building a website or app, you want to be able to go back to a previous version if something breaks. For regular code files, this is straightforward - you just save different versions of your files.

But databases are trickier. A database isn’t just files sitting on your computer - it’s a living system with data, rules, and relationships. You can’t just copy and paste a database like you would a text file. Instead, you need to create step-by-step instructions (called migrations) that tell the database how to change from one version to another.

It’s like having a recipe that transforms your kitchen from one setup to another, rather than just having a picture of what the final kitchen should look like. I finally set up this system so I can safely make changes to my database without worrying about breaking everything and having no way to fix it.

Nerdy Details

Database version control with Supabase follows a migration-based approach that’s fundamentally different from traditional file-based version control. Database migrations are SQL statements that create, update, or delete your existing database schemas. They are a common way of tracking changes to your database over time.

The key insight is understanding the difference between declarative and imperative approaches. While your application code can be version controlled declaratively (Git knows the final state of each file), databases require an imperative approach using migration files.

Here’s the current best practice workflow for Supabase database version control in 2025:

1. Initialize Migration System

# Generate a new migration file
supabase migration new create_initial_schema

# This creates a file in supabase/migrations/ with timestamp

2. Write Migration SQL Each migration file should contain the SQL needed to move your database forward:

-- 20250607120000_create_initial_schema.sql
create table if not exists employees (
  id bigint primary key generated always as identity,
  name text not null,
  email text,
  created_at timestamptz default now()
);

-- Create triggers
create or replace function update_timestamp()
returns trigger as $$
begin
  new.updated_at = now();
  return new;
end;
$$ language plpgsql;

3. Apply and Test Locally

# Apply migration locally
supabase db reset

# Test your changes
supabase start

4. Version Control Edge Functions When you’re ready to go to production, store Edge Functions code in a source code repository (e.g. git) and deploy it using one of the CI integrations.

For Edge Functions, the current best practice is:

  • Use the dashboard editor only for prototyping
  • Store production code in Git repositories
  • Deploy via CI/CD pipelines
  • Use environment variables for secrets instead of hardcoding them into function code

5. Production Deployment

# Deploy migrations to production
supabase db push

# Deploy edge functions
supabase functions deploy --project-ref your-project-ref

Modern Migration Management Features: The CLI now includes a “diff” feature - you can create tables via the Dashboard and then generate migrations automatically by running supabase db diff. This bridges the gap between GUI-based development and proper version control.

Supabase now offers preview environments that automatically create isolated instances for each GitHub pull request, with migrations automatically applied to keep your team working from the same source of truth.

The tooling has improved significantly in 2025, with better testing capabilities and the new Postgres Language Server providing linting, syntax highlighting, and auto-completion for SQL.

Next Week

It’s going to be a shorter week, but the focus remains on bug squashing. I already have a list of issues I’ve identified that need fixing. I’m also planning to polish up the subscription interaction flows with customers - making sure the billing and account management experience is smooth before alpha testing begins.

The goal is to get everything stable and polished enough for real users to start testing the app without running into frustrating bugs or confusing user experience issues.