👋 Hey friends,

Here’s what I’ve got in store for you this week:

  • Another snippet from The Backend Lowdown

  • A neat tool I use to better visualize logs in my terminal

Let’s get into it! 👇

Happy Holidays

Whether you’re celebrating or just taking it easy, I hope you have a great week.
Thanks for being here. Your support genuinely means a lot to me.

The Backend Lowdown: Chapter 1 Preview

Every newsletter will include a snippet from my book in progress, The Backend Lowdown, available for $5 right now on Gumroad!

Get The Backend Lowdown →

Patterns for Safe Migrations (cont.)

Now that we've covered how migrations can go wrong, let's talk about how to make them go right.

Most safe migrations boil down to a few key principles:

  • Avoid locking large tables

  • Break changes into multiple steps

  • Backfill data carefully

  • Avoid assumptions about data shape

  • Use the database's features to your advantage

Here are some common safe patterns, with real examples and tradeoffs explained:

Backfill in Batches, Not All At Once

Large-scale updates can trigger row locks, long-running transactions, and excessive disk I/O.

Safe pattern:

User.find_in_batches(batch_size: 1000) do |batch|
  batch.each do |user|
    user.update_columns(status: "active")
  end
end

You can also throttle the backfill with sleep if necessary.

Make Destructive Changes Gradually

Dropping a column should be the last step in a cleanup - not the first.

Safe approach:

  1. Stop using the column in code

  2. Mark it ignored in your ORM (e.g. self.ignored_columns)

  3. Deploy and monitor

  4. Drop the column in a later migration

This lets you surface unexpected usage before it becomes a production incident.

Use Feature Flags for Behavior Changes

If your migration enables new behavior - like a new enum value or a changed default - guard that logic behind a feature flag or runtime toggle.

This lets you:

  • Deploy the schema independently of the code

  • Roll back without undoing the migration

  • Test incrementally before committing fully

Tool of the Week: tailspin

If you work on the backend at all, you know how painful it can be to try and find the needle in the haystack that is your server logs in the terminal. It doesn’t matter if you’re running Rails, Phoenix, or Django, they all output a plethora of information and usually it’s all a single color. This makes parsing them difficult and while you can grep or try to search via your terminal, a lot of the time you’re just trying to spot a few things and those methods are slow or overkill.

Enter: tailspin, a log file highlighter that helps show you the important bits in your server logs. I’ve been using it with a side project of mine that relies on Phoenix and it’s been helpful. Here’s a side-by-side comparison:

Regular ol’ Phoenix server logs

With tailspin 😎

It doesn’t have to just be a log file, as you can see from the above I just pipe my server logs into tailspin via:

mix phx.server 2>&1 | tailspin

Tailspin has a decent amount of configurability so you can go wild customizing what you want to see and how it should look. I recommend it if you spend any time at all looking at logs! It’s quick to install, easy to run, and gives you a good start right out the box.

That’s a wrap for this week. If something here made your day smoother, feel free to reply and tell me about it. And if you think a friend or teammate would enjoy this too, I’d be grateful if you shared it with them.

Until next time,
Steven

Keep Reading