๐ก Home > ๐ค AI Blog | โฎ๏ธ โญ๏ธ
2026-03-22 | ๐ง Smarter Image Generation โ Caching, Prioritization & Rate Limiting

๐ฏ 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 exhaustion | Message contains โquotaโ + โdailyโ/โper dayโ/โPerDayโ | ๐ Stop the job |
| โฑ๏ธ Per-minute rate limit | Message 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:
- โ Why are there duplicate
updated:fields? โ BecauseupdateFrontmatterTimestampinserts a new line instead of replacing the existing one. - โ Why does it insert instead of replace? โ Because regex pattern matching fails on certain valid YAML.
- โ 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.
- โ Why was regex used for YAML? โ Because the original implementation treated frontmatter as line-oriented text instead of structured data.
- โ Why not use a proper YAML parser? โ No principled reason โ
js-yamlwas 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:
- โ Why are there two fields with the same content? โ Because the caching logic stored the description in a new
image_descriptionfield while also writing it toimage_prompt. - โ Why was a new field created? โ Because the caching implementation treated description caching as a separate concern from prompt storage.
- โ Why didnโt it reuse
image_prompt? โ Because the design didnโt recognize thatimage_promptalready held the description when a describer was used. - โ Why does
image_prompthold the description? โ Because when a describer is used, the description IS the prompt โ the same text goes to the image generator. - โ 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 tests | 180 |
| ๐งช Total repo tests | 927 |
| โฑ๏ธ Test suite duration | < 600ms |
| ๐ Spec document | ~350 lines |
| ๐ Bugs fixed | 3 |
๐ฏ 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
โ Bryan Grounds (@bagrounds.bsky.social) 2026-04-02T09:28:37.000Z
https://bagrounds.org/ai-blog/2026-03-22-smarter-image-generation-v2