Skip to the content.

← All patterns

Example (Zeeguu): When the prompt that generates audio lesson scripts was improved, the ~900 stored audio_lesson_meaning rows produced under the previous prompt were neither regenerated eagerly nor deleted. Instead, each affected row received a deprecated_at timestamp, and the cache-lookup helper (AudioLessonMeaning.find()) was gated to skip deprecated rows. New daily lessons request a fresh row and trigger regeneration under the new prompt; existing daily lessons that already reference a deprecated row keep playing their old audio without breaking.

Forces: When a prompt or model improves, the obvious responses each have a serious drawback:

None of these are good defaults for production systems where LLM-generated artifacts are referenced from user-visible history and are also targets for reuse.

Solution: Mark stale rows as deprecated rather than mutating or removing them. Gate the cache-lookup / reuse path to skip deprecated rows, forcing fresh generation on next demand. Existing references to a deprecated row remain valid — the row keeps its content for historical playback — but no new consumer picks it up. Regeneration cost is paid lazily, amortized over normal access patterns, and only for content that is actually requested again.

Notes:

← All patterns