Skip to main content
Laravel, shipping fast.

Chapter 12

Data Management

Julian Beaujardin

Every row you write outlives the feature that wrote it. A license gets issued, a domain gets connected, a bearer token gets minted, and the record sits there long after the request that created it is forgotten. Nobody schedules a meeting about data management. It accumulates quietly until someone asks "can we delete this user's data" or "why is this table forty gigabytes," and the answer is a scramble instead of a plan.

This chapter covers what a first pass at data management always skips: retention declared on the model, not remembered inside a cron job; migrations and backfills that survive being interrupted halfway through a live table; what actually happens, mechanically, when someone asks you to delete their account; and archiving as a design decision made before the delete, not a recovery plan wished for after.

Data you don't have an intentional plan for is a liability wearing the disguise of an asset.

Data has a cost and an owner

Here's the rule: every column, every JSON blob, every table you add to metadata or settings is something your team now owns forever, whether anyone reads it again or not. Storage is the cheap part. The expensive part is knowing what the data means, whether it's safe to delete, and who's allowed to ask for it back.

Look at how settings grows on a Bearer over a couple of years. One release adds server.products keyed by plan. A later release needs it keyed by provider instead, because plans and providers stopped being a one-to-one mapping. Now you own two shapes of the same data until somebody writes a migration to collapse them. Nobody planned that shape change; it happened one feature at a time, and the JSON blob absorbed it silently because JSON blobs don't complain.

Ownership means something specific: for every table, one person or team can answer "why do we keep this, and for how long" without opening the code. If nobody can answer that, the data doesn't have an owner. It has a landlord who's stopped paying attention.

  • Cost: storage, backup size, query planning, and the cognitive load of a schema nobody fully understands.
  • Owner: the team whose feature the data serves, not the team whose migration happened to create the column.
  • Justification: a one-line reason that survives the person who wrote it leaving the company.

A table with no owner and no justification isn't neutral. It's debt with a slower interest rate than code debt, which is exactly why it's more dangerous. Nobody notices until the bill is due.