Skip to Content
Design NotesWhy recipes own snapshots of profiles

Why recipes own snapshots of profiles

In BrewDesigner, water profiles, mash profiles, and fermentation profiles are reusable libraries. Recipes don’t reference them by foreign key at render time — they own a snapshot of the profile at the moment the recipe was created or last edited.

The pattern

When you attach a mash profile to a recipe, the app copies the profile’s steps, temperatures, and durations into a recipe-scoped table (recipe_mash + recipe_mash_steps). The original profile in your library is unaffected.

The recipe’s snapshot stores two pointers to its source:

  • source_profile_name — the human label, frozen at copy time.
  • source_profile_id — a foreign key with ON DELETE SET NULL. It’s lineage only; if you delete the source profile, the snapshot stays intact and the FK becomes null.

Why this design

We considered three alternatives:

  1. Hard FK to the profile. Edits to the profile would silently change every recipe that used it — unacceptable.
  2. Versioned profiles. Every save of a profile creates a new version; recipes pin a version. Solves the silent-edit problem but explodes the number of profile rows over time.
  3. Snapshots. Each recipe gets its own copy. Profiles are just templates. Edits to a recipe’s mash don’t touch the library; edits to the library don’t touch existing recipes.

We picked snapshots because:

  • The data is small (a few rows of mash steps per recipe).
  • It maps cleanly to how brewers think: “this batch used this mash, even if I tweak the template later.”
  • It makes recipes self-contained for export, sharing, and import.

Consequences

  • Editing a recipe’s mash never affects your library — there’s no “save this back to the profile” button. If you want to update the library, do it in the profiles page.
  • Importing a recipe from BeerXML / BeerSmith populates the snapshot directly without needing a matching library entry.
  • Deleting a profile from your library is safe; existing recipes keep working.
Last updated on