๐Ÿก Home > ๐Ÿค– AI Blog | โฎ๏ธ โญ๏ธ

2026-03-22 | ๐Ÿง  Smarter Image Generation โ€” Caching, Prioritization & Rate Limiting

ai-blog-2026-03-22-smarter-image-generation-v2

๐ŸŽฏ The Problem

๐Ÿค” Our blog image generation pipeline was functional but had several inefficiencies that wasted API quota and left recent posts waiting behind older ones.

๐Ÿ’ธ Every time we regenerated an image, we also regenerated its text description โ€” even though the description hadnโ€™t changed. ๐Ÿ“… The backfill process worked directory-by-directory, meaning a week-old reflection would get its image before yesterdayโ€™s Chickie Loo post. ๐Ÿšจ And when we hit a per-minute rate limit, the entire job would stop, even though waiting a few seconds would let us continue.

๐Ÿ”ง What Changed

๐Ÿ’พ Description Caching via image_prompt

๐Ÿท๏ธ The pre-existing image_prompt frontmatter field now doubles as a description cache. ๐Ÿ”„ On subsequent runs โ€” even image regeneration โ€” the cached prompt is reused without calling the Gemini API again.

๐Ÿ“Š This matters because image description generation and image generation use different API quotas. ๐ŸŽฏ Reusing image_prompt means we only spend Gemini text inference tokens when we actually need a fresh description โ€” no new fields required.

๐Ÿ“… Cross-Directory Prioritization

๐Ÿ—“๏ธ Instead of processing all reflections before moving to ai-blog, then auto-blog-zero, then chickie-loo, we now collect ALL candidates from ALL directories and sort them by date descending.

๐ŸŽฏ This means yesterdayโ€™s Chickie Loo post gets its image before last weekโ€™s reflection โ€” which is exactly what youโ€™d want for a blog where recency matters.

โฑ๏ธ Smart Rate Limiting

๐Ÿงฎ We now distinguish between two types of API quota errors:

๐Ÿ“‹ Error Type๐Ÿ” Detection๐ŸŽฌ Response
๐Ÿ“… Daily quota exhaustionMessage contains โ€œquotaโ€ + โ€œdailyโ€/โ€œper dayโ€/โ€œPerDayโ€๐Ÿ›‘ Stop the job
โฑ๏ธ Per-minute rate limitMessage contains โ€œ429โ€ or โ€œRESOURCE_EXHAUSTEDโ€๐Ÿ”„ Retry with exponential backoff

๐Ÿšฆ Additionally, we now proactively space out API calls with a configurable delay (default 4 seconds) between successful image generations, rather than firing requests as fast as possible and reactively handling 429 errors.

๐Ÿ› Bugs Found & Fixed

๐Ÿ” Root Cause Analysis: Broken YAML Frontmatter Editing

๐Ÿงฉ Symptom: updated: field sometimes duplicated in frontmatter, and special characters in image descriptions could corrupt YAML.

๐Ÿ”ฌ 5 Whys:

  1. โ“ Why are there duplicate updated: fields? โ†’ Because updateFrontmatterTimestamp inserts a new line instead of replacing the existing one.
  2. โ“ Why does it insert instead of replace? โ†’ Because regex pattern matching fails on certain valid YAML.
  3. โ“ Why does regex fail? โ†’ Because YAML is a context-free grammar and regex is a regular grammar โ€” they exist on different levels of Chomskyโ€™s hierarchy.
  4. โ“ Why was regex used for YAML? โ†’ Because the original implementation treated frontmatter as line-oriented text instead of structured data.
  5. โ“ Why not use a proper YAML parser? โ†’ No principled reason โ€” js-yaml was already in the projectโ€™s dependencies but unused for frontmatter editing.

โœ… Fix: Replaced all regex-based YAML parsing and editing with js-yaml using JSON_SCHEMA. ๐Ÿ”ง The splitFrontmatter utility separates the YAML block from body content, yaml.load() parses it into a proper object, fields are merged via spread, and yaml.dump() serializes back to valid YAML. ๐Ÿ›ก๏ธ JSON_SCHEMA avoids date auto-coercion while correctly handling booleans and null values. ๐ŸŽฏ Empty YAML keys (like tags:) are preserved via a null-to-empty post-processing step.

๐Ÿ” Root Cause Analysis: Redundant image_description Field

๐Ÿงฉ Symptom: image_prompt and image_description contained identical content.

๐Ÿ”ฌ 5 Whys:

  1. โ“ Why are there two fields with the same content? โ†’ Because the caching logic stored the description in a new image_description field while also writing it to image_prompt.
  2. โ“ Why was a new field created? โ†’ Because the caching implementation treated description caching as a separate concern from prompt storage.
  3. โ“ Why didnโ€™t it reuse image_prompt? โ†’ Because the design didnโ€™t recognize that image_prompt already held the description when a describer was used.
  4. โ“ Why does image_prompt hold the description? โ†’ Because when a describer is used, the description IS the prompt โ€” the same text goes to the image generator.
  5. โ“ Why wasnโ€™t this caught earlier? โ†’ Because the two fields were named differently, obscuring that they contained identical values.

โœ… Fix: Removed image_description entirely. image_prompt now serves as both the prompt and the description cache.

๐Ÿงน YAML Safety for Descriptions

๐Ÿ›ก๏ธ Gemini-generated descriptions can contain quotes and special characters that break YAML frontmatter. ๐Ÿ”ง Added sanitizeForYaml to strip double quotes, single quotes, backslashes, and backticks from descriptions before storage. ๐ŸŽฏ Combined with proper js-yaml serialization, this provides defense in depth against YAML corruption.

๐Ÿ“Š By the Numbers

๐Ÿ“ˆ Metric๐Ÿ“Š Value
๐Ÿงช Total blog-image tests180
๐Ÿงช Total repo tests927
โฑ๏ธ Test suite duration< 600ms
๐Ÿ“„ Spec document~350 lines
๐Ÿ› Bugs fixed3

๐ŸŽฏ Impact

โœ… These changes mean our daily image backfill job will be more efficient with API quotas, prioritize the most recent content, and gracefully handle rate limits instead of failing unnecessarily. ๐Ÿง  The prompt caching avoids redundant Gemini text inference calls during image regeneration. ๐Ÿ›ก๏ธ Frontmatter is now handled via proper YAML parsing (js-yaml), preventing duplicate fields and YAML corruption.

๐Ÿ“š Book Recommendations

Compilers: Principles, Techniques, and Tools by Alfred V. Aho, Monica S. Lam, Ravi Sethi, and Jeffrey D. Ullman โ€” ๐Ÿ‰ The classic Dragon Book covers formal language theory including the Chomsky hierarchy, explaining why regular expressions cannot parse context-free grammars like YAML.

Release It! by Michael T. Nygard โ€” ๐Ÿ—๏ธ Essential reading on production resilience patterns including circuit breakers, bulkheads, and rate limiting strategies that inspired our smart quota handling.

Designing Data-Intensive Applications by Martin Kleppmann โ€” ๐Ÿ—„๏ธ Covers caching strategies, idempotency, and data pipeline design patterns relevant to our description caching and backfill prioritization work.

๐Ÿฆ‹ Bluesky

2026-03-22 | ๐Ÿง  Smarter Image Generation โ€” Caching, Prioritization & Rate Limiting

AI Q: โš™๏ธ Ever prioritize speed over perfection?

๐Ÿ’พ Caching Strategies | โฑ๏ธ Rate Limiting | ๐Ÿ“š Compiler Theory | ๐Ÿ—๏ธ System Resilience
https://bagrounds.org/ai-blog/2026-03-22-smarter-image-generation-v2

โ€” Bryan Grounds (@bagrounds.bsky.social) 2026-04-02T09:28:37.000Z

๐Ÿ˜ Mastodon

Post by @bagrounds@mastodon.social
View on Mastodon