Why We Generate Carousel Slides on First View, Not on Create
The Onboarding Bottleneck
When a business onboards with Jiwa AI, we generate an entire content calendar โ feed posts, stories, carousels โ all in one pipeline. The goal is speed: paste a URL, get content in minutes. Every second counts.
Carousels are the most expensive content type we produce. Each one needs six slides with individually crafted text overlays, each persisted to storage. That's six image processing operations, six uploads, and an AI call to generate the slide content structure. Multiply that by however many carousel posts are in the calendar, and you've added significant time to an onboarding that's supposed to feel instant.
Most Content Never Gets Viewed Immediately
Here's the insight that changed our approach: during onboarding, users typically look at the first one or two posts. They scan the calendar, maybe click into a feed post to check the caption. They rarely open every carousel and swipe through all six slides on their first visit.
We were spending compute and time generating slides that nobody would see for days โ or possibly ever, if the user decided to regenerate or delete the post. The onboarding pipeline was doing work that didn't need to happen yet.
Generate When Someone Actually Looks
We moved carousel slide generation out of the onboarding pipeline entirely. Instead, when a user clicks on a carousel post in their dashboard, the system checks whether slides exist. If they don't, it triggers generation right then โ fetching the base image, calling AI for slide content, applying text overlays, and persisting everything to storage.
The user sees a brief loading state with a spinner, and within a few seconds the carousel appears with all six slides ready to swipe through. Once generated, the slides are cached permanently โ subsequent views are instant.
This is a classic lazy evaluation pattern, applied to content generation. Don't compute what you don't need yet. Wait until the moment of demand.
The Trade-off We Accepted
Lazy generation introduces a visible delay the first time someone views a carousel. That's a real trade-off. Instead of everything being ready upfront, there's a spinner for a few seconds.
We decided this was the right call for three reasons. First, onboarding speed matters more than carousel viewing speed โ the first impression is the onboarding flow, not the sixth slide of a carousel. Second, the delay only happens once per carousel, and it's short enough that it feels like loading rather than waiting. Third, some carousel posts may never be viewed at all, so generating them eagerly would be pure waste.
The alternative โ pre-generating everything during onboarding โ would add thirty to sixty seconds to a flow we've optimized to complete in under two minutes. That felt like the wrong trade-off.
Guarding Against Duplicate Work
One subtlety: if a user rapidly clicks in and out of a carousel post, or if multiple tabs trigger the same generation, we'd get duplicate work. The system checks for existing slides before starting generation, and the frontend tracks whether a generation is already in progress to prevent duplicate API calls.
The database acts as the source of truth. Once slides are written, any subsequent request returns them immediately without regeneration.
A Pattern Worth Repeating
Lazy generation isn't a new idea, but it's underused in AI-powered products. The instinct is to generate everything upfront so it "just works." But when generation is expensive โ both in compute cost and wall-clock time โ deferring work to the moment of need often produces a better user experience overall.
The onboarding is faster. The compute bill is lower. And the content is just as ready when the user actually wants it. Sometimes the best optimization is simply not doing work that nobody asked for yet.