Vibe Engines
YouTube

Vibe Engines is free, interactive AI engineering & system design — runs in your browser. Pick a learning path

AI System Design

Design an AI Ad Creative Platform

Step 1 / 9

Learn AI system design by building a platform that generates ad creative — images, copy, and video variants — at scale for advertisers, built ON TOP of generative models rather than serving them…

The numbers to beatfixed A/B splitwastes spend on the fixed period's losersbandit allocationcontinuously reallocates toward winnerssame total budgetmore value extracted

The whole design, in writing

Every step of the build above, written out: the problem each piece solves, the option that was taken and the ones that were not, the numbers, and how it fails in production.

The big idea

A platform built ON generative models, not just serving them

Generating one nice-looking ad image is a solved problem — plug into any image model. What's genuinely hard is everything AROUND that: generating dozens of testable variants, making absolutely sure none of them violates ad-platform policy (a violation can get the whole account suspended), tracking commercial usage rights, and actually learning from real performance data instead of guessing.

Advertisersubmits a brief
New in this step: Advertiser.

We'll build the product layer: programmatic variant generation, a fail-closed compliance gate, rights tracking, dynamic budget allocation across variants, and a real performance feedback loop.

What the new pieces do

Advertiserclient
A brand or marketer wanting many tested creative variants fast, not one hand-designed ad that may or may not perform.

Step 1 · The baseline

One hand-designed creative per campaign

Simplest version: a designer manually produces one ad creative per campaign. What's the real limitation?

Advertisersubmits a briefCreative APIbrief intake
New in this step: Creative API.

One manually-designed creative per campaign. What's the core limitation for a real advertiser?

  1. Advertising performance varies enormously by wording, imagery, and CTA in ways that are genuinely hard to predict up front — a single creative, however well-designed, is a single untested guess about what will actually convert.

  2. Advertisers fundamentally need to TEST — run multiple variants against real audiences and let actual performance data reveal what works, which a single hand-made creative structurally can't provide.

  3. Production speed for ONE creative is a secondary concern — the deeper limitation is the complete absence of any tested alternative to compare it against.

A single hand-designed creative is an untested guess — real ad performance depends heavily on wording, imagery, and CTA choices that are hard to predict without actually testing alternatives against real audiences. The platform's value is enabling that testing at scale.

Why this piece earns its place

One creative in market produces one number, and nothing in that number separates a weak headline from a badly chosen audience or a bid that never won the auctions worth winning. Every post-mortem becomes an argument between the people who made each of those three decisions, and none of them can be settled with the evidence on hand. Running variants concurrently removes the time-and-market confound — comparing this month’s creative to last month’s compares the market as well — but it does not remove the delivery one, because the ad platform still chooses who sees each variant, which is the problem Step 5 has to pick up again. This framing also fixes the unit the rest of the platform addresses: the brief, not the creative. Compliance, rights, budget and formatting all hang off a brief and its children, and retrofitting that parentage later is genuinely painful. Where the baseline still wins: a flagship campaign whose creative is the asset — a shot film, a licensed face — cannot be tested into existence, and in a regulated category where every line needs legal sign-off before it runs, a wide batch costs more in review than the test can return.

What the new pieces do

Creative APIgateway
Accepts a creative brief (brand guidelines, product, goal) and orchestrates everything that turns it into tested, live ad variants.

Step 2 · Programmatic variant generation

Many variants, not one "best" guess

Should the platform try to generate the single best creative from a brief, or something else entirely?

Creative APIbrief intakeVariant Generatorimages, copy, CTAs
New in this step: Variant Generator.

Given a creative brief, should the platform aim to generate ONE optimal creative, or many?

  1. No generation process can reliably predict real-world ad performance in advance — "best judgment" is still a guess, and a single output gives advertisers nothing to actually TEST against, defeating the entire empirical value proposition from Step 1.

  2. Generating many genuinely different variants gives advertisers real alternatives to test against actual audiences — the platform's job isn't to guess the single winner, it's to produce a good pool of candidates and let real performance data determine which one(s) actually win.

  3. Making variance opt-in misses the point — testing multiple variants against each other IS the core value proposition, not an optional extra most advertisers would need to specifically ask for.

Build a Variant Generator that programmatically produces many creative variants from a single brief — different headlines, images, and calls-to-action — explicitly to enable real testing, not to guess a single "best" answer up front.

Why this piece earns its place

Diversity has to be engineered; it does not fall out of sampling the same model repeatedly. Turn the temperature up and you mostly get rewordings of one idea, and a batch whose variants differ only in phrasing is a batch whose real differences are tiny — separable in principle, but only at a traffic cost far past what the campaign has to spend, which in practice means the test ends without a verdict. So vary along named axes: the hook, the image subject, the call-to-action verb, the offer framing. Bigger axes open bigger gaps, and a gap is what a finite budget can actually resolve. Write the axis and its value onto each variant as structured metadata at generation time, because a feedback loop can only learn from attributes it can name, and a variant pulled later can only be traced to its siblings through them. The last thing experience teaches is that batch size is bounded by traffic, not by generation cost — arms need impressions before they mean anything — so it belongs in the campaign’s own parameters, sized against the budget that campaign actually has.

What the new pieces do

Variant Generatorservice
Programmatically produces many creative variants from one brief — different headlines, images, and calls-to-action — for real A/B testing, not just one "best guess."

Step 3 · The compliance gate fails closed

One violation can suspend the whole account

Every generated variant needs to be checked against brand guidelines and ad-platform policy before going live. If that check is temporarily unavailable, should variants publish anyway?

Creative APIbrief intakeVariant Generatorimages, copy, CTAsBrand-Safety Gatefails closed
New in this step: Brand-Safety Gate.

The compliance check is briefly unavailable. Should variant publishing continue without it?

  1. A single generated variant that violates ad-platform policy (a prohibited claim, restricted content) can get the ENTIRE ad account suspended — a consequence wildly disproportionate to whatever delay a brief compliance-check outage would cause. This isn't a trade worth making.

  2. Given the asymmetric stakes (a brief delay vs. a potential account suspension affecting every campaign that account runs), blocking publication until the gate is healthy again is the only defensible default — this is the same fail-closed principle used for spam filters and model-eval gates elsewhere, applied here because the downside of failing open is severe.

  3. Sampling still lets some fraction of violating content through — for a risk this asymmetric (one violation can suspend the whole account), partial checking isn't meaningfully safer than no checking.

Make the Brand-Safety Gate fail closed: while unavailable, generation and drafting continue, but no variant can be published to a live ad platform. The stakes — a single violation risking suspension of the entire ad account — make this the only defensible default, regardless of the inconvenience of a delay.

Why this piece earns its place

Failing closed makes this gate the availability floor for the entire product: an hour of gate downtime is an hour in which nothing ships, so its own uptime is now the number you defend. That argues for keeping it small and dependency-light — a chain of third-party model calls in the publish path buys accuracy and sells availability. It also checks two things that behave nothing alike. Brand rules belong to the advertiser: written down, versioned, changed on their schedule. Ad-platform policy belongs to the platform and moves without telling you, so there is no platform version number available to stamp. What is stampable is your own snapshot of that policy — the encoded ruleset the gate actually ran, carrying an id — and every approval should record it. That will not tell you which of the platform’s rules moved; it tells you what each live creative was cleared against, which turns the Step 8 re-check from a sweep of everything into a much smaller set. The failure to watch for is not the violation, it is strictness: a gate that rejects too much trains advertisers to export the creative and upload it by hand, and every variant that leaves through that door takes its performance data with it.

What the new pieces do

Brand-Safety Gateservice
Checks every variant against brand guidelines AND ad-platform policy before it can go live — the highest-stakes gate, since a violation risks account suspension.

Step 4 · Rights and commercial licensing

Generated doesn't automatically mean usable

A generated image might resemble a real person, use elements that echo a trademark, or come from a model whose outputs have ambiguous commercial usage rights. Is passing brand/policy checks alone sufficient to publish?

Variant Generatorimages, copy, CTAsBrand-Safety Gatefails closedRights & Licensingcommercial-use tracking
New in this step: Rights & Licensing.

A variant passes brand-safety and platform-policy checks. Is that alone sufficient to clear it for a paid ad?

  1. Brand and platform-policy checks assess CONTENT appropriateness — they don't verify whether the specific generated asset is actually licensed for commercial advertising use, or whether it inadvertently resembles a real person's likeness or a trademarked design, which are separate legal risks entirely.

  2. Rights and licensing is a genuinely distinct concern from content-policy compliance — a perfectly brand-appropriate, policy-compliant image can still carry real legal risk if it wasn't actually licensed for commercial use, or if it incidentally resembles a real person's likeness without consent.

  3. Generated content's commercial usage rights depend on the specific model/training data and licensing terms involved — this is far from automatic, and assuming it away invites real legal exposure.

Maintain a Rights & Licensing tracker separate from content-policy checks: it verifies a generated asset is actually licensed for commercial ad use and flags likeness or trademark risk before publishing — a distinct legal concern from whether the content is appropriately worded or policy-compliant.

Why this piece earns its place

Rights is a record-keeping problem more than a checking problem. The check runs once; the obligation lasts as long as the ad runs and well beyond it. So what this component must produce is not a pass flag but a provenance record — which model, which model version, which prompt, which source assets, who approved it — written at generation time. Months later a letter arrives naming one image, and a boolean is not evidence. The second-order consequence is that today’s answer may not survive the year. Terms attach to a model version, and a vendor can revise the terms it offers — normally binding what you generate next rather than reaching backwards, but the moment one lands, everything already live under the old terms has to be re-examined rather than assumed. Your own upgrade is the cleaner case: it moves the position for future generations only, which is precisely what the provenance record lets you demonstrate instead of argue. The tracker therefore needs a sweep — show me every running creative produced by this model version — and not only a per-asset lookup, and it needs to have been built before the day you need it. You can skip most of this when generation draws on a closed catalogue you already license: then the rights answer is constant and one license per source carries it.

What the new pieces do

Rights & Licensingdata
Tracks whether a given generated asset is actually licensed for commercial ad use, and flags likeness/trademark risk before publishing.

Step 5 · Dynamic budget allocation

Beyond a fixed A/B split

Many approved variants are ready to run. Should ad spend be split evenly across all of them for a fixed test period, then pick a winner?

Brand-Safety Gatefails closedBandit Allocatordynamic budget split
New in this step: Bandit Allocator.

Several approved variants are ready. Split budget evenly across all of them for a fixed period?

  1. A fixed even split spends real advertising budget on clearly-underperforming variants for the ENTIRE test duration, even once it's become fairly obvious they're losing — wasting spend that could have gone toward variants that are actually converting.

  2. A bandit allocator treats each variant as an "arm" and continuously reallocates spend toward whichever is currently performing best, based on accumulating real data — this captures much more value from the SAME total budget than a fixed even split that only reacts at the end of the test period.

  3. Random daily rotation doesn't use performance DATA to inform allocation at all — it's not meaningfully better than a fixed split and actively wastes budget on days a clearly weaker variant happens to be selected.

Use a Bandit Allocator: rather than a fixed even split, continuously shift spend toward variants demonstrating stronger real performance and away from weaker ones, using accumulating data throughout the test rather than only reacting at a fixed test's conclusion.

Why this piece earns its place

The algorithm is the easy part. The reward signal decides whether this helps or quietly hurts. A click is recorded the moment it happens; a purchase lands later, often after the session that caused it has closed. The allocator converges on whatever you feed it — give it clicks and it will reliably find the variant that wins the click and loses the sale, and every dashboard the allocator itself reports on will read that as success. So pick the metric whose delay you can tolerate, and say out loud that arms keep drawing budget throughout the window in which their own outcome is still unknown. Worth remembering too that spend is a bid, not an impression: the ad platform’s own optimizer sits between the two and decides who sees what, so an arm’s result is confounded by the audience the platform chose to send it. The knob that belongs to the campaign rather than the platform is the exploration floor, the share of spend held back for arms that currently look weak. And a variant added mid-flight has no history, so it must be seeded deliberately or it starves the moment it is born.

  • fixed A/B splitwastes spend on the fixed period's losers
  • bandit allocationcontinuously reallocates toward winners
  • same total budgetmore value extracted

What the new pieces do

Bandit Allocatorservice
Shifts spend toward better-performing variants in real time, rather than splitting budget evenly across all of them for a fixed test duration.

Step 6 · Close the performance feedback loop

Learn from what actually converted

Performance data accumulates on every variant. Should that just sit in a dashboard, or feed back into anything?

Variant Generatorperformance-informedBrand-Safety Gatefails closedRights & Licensingcommercial-use trackingBandit Allocatordynamic budget splitPerformance Metricsfeeds future generation
New in this step: Performance Metrics.

Feed Performance Metrics back into future Variant Generation: not retraining the underlying generative model per campaign, but using observed patterns (which styles, tones, or structures tended to convert) to bias what kinds of variants get generated for future briefs — the system gets measurably better at proposing promising variants over time, informed by real outcomes rather than generating blind every time.

Why this piece earns its place

A closed loop feeds on its own output, and that is the risk worth naming. The allocator can only spend on variants that were generated, and generation is now biased by what the allocator spent on, so an approach nobody tried accumulates no evidence and stops being tried. The pool narrows onto a local optimum while average performance keeps rising — which, from the outside, is exactly what improvement looks like. The defence is structural: reserve part of every batch for variants deliberately off the learned distribution, and judge the loop by whether attributes new to an account still win sometimes, rather than by a mean that will climb either way. Scope matters as much as mechanism. What converts is specific to an advertiser and their audience, so learning pools per account by default; a brand’s winning hook surfacing in a competitor’s generated variants is the kind of thing that ends a contract. And version the learned bias like any other input to generation — when a week of output gets worse, you want to roll back a named set, not guess which outcomes taught it that.

What the new pieces do

Performance Metricsdata
Tracks which variants — and which style/attribute patterns — actually converted, closing the loop back into future generation.

Step 7 · Platform-specific formatting

One approved creative, many required shapes

An approved creative needs to run on Instagram Stories (vertical), a Google Display banner (wide), and a feed post (square) — each with different required dimensions and format constraints.

Bandit Allocatordynamic budget splitPlatform Formatterper-channel specs
New in this step: Platform Formatter.

A Platform Formatter automatically adapts approved creative into each target platform's required aspect ratios and format specs — generating the necessary crops/resizes rather than requiring the advertiser to manually reformat one creative for every channel it needs to run on.

Why this piece earns its place

Reformatting is not a lossless transform, and that is the sharp edge under an otherwise clean separation. A crop can drop the disclaimer, the legal line, the logo, or the part of the frame that made a claim defensible — and the result is content nobody approved, wearing an approval. The workable rule: a format that preserves every approved element inherits the approval, while one that drops or reflows an element is new content and goes back through the gate. That distinction is only cheap to make automatically if the formatter works from a layered composition — background, subject, headline, legal, logo, each with its own safe region — rather than re-cropping a flat rendered image, which reaches back into how Step 2 generates in the first place. Platform specs are the second trap. File-size caps, text-in-image limits and duration rules are external and change without asking you, so hold them as versioned data the formatter reads, not constants compiled into it. A rejection at upload then reads as a stale spec, which is a fix, rather than a formatter bug, which is a hunt.

What the new pieces do

Platform Formatterservice
Auto-adapts approved creative into the exact aspect ratios and formats each ad platform (Stories, Display, feed) actually requires.

Step 8 · The sharp edges

Winning isn't the same as safe, and generation isn't free

Two real pressures: a variant that's genuinely winning on clicks but reads as manipulative once more people see it, and the real cost of generating dozens of variants, especially video, before knowing which will actually perform.

AdvertiserCreative APIVariant GeneratorBrand-Safety GateRights & LicensingBandit AllocatorPerformance MetricsPlatform Formatter
The system as it stands at this step. · swipe to pan the diagram

Run ongoing compliance re-checks on live, high-performing variants, not just a one-time gate at generation — a variant can start looking manipulative or attract complaints only once it's seen by a wider audience, and a metric win doesn't override a compliance failure discovered later. For cost, use tiered generation: generate cheap image/copy variants first, gather early performance signal cheaply, and only generate expensive formats (full video) for the variants that have already shown promise — rather than producing every format for every variant up front.

Why this piece earns its place

Pulling a variant is an external action, and that is where this gets operational. The creative is already live on platforms you do not control, so the pull is an API call that can be rate-limited, rejected, or silently slow — which means there is a window in which your database says stopped and real people are still being shown the ad. Treat the kill path as its own queue, with retries and a verified terminal state, and never let a status in your own tables stand in for what a platform is actually serving. The unit of the pull matters too. Variants from one brief share attributes, so whatever read as manipulative in the flagged one probably sits in its siblings — recall the attribute, not the single variant, or the allocator promotes its twin at the next reallocation and you meet the same complaint under a new id. Re-checking everything forever is wasted compute; the triggers worth paying for are the three things that change the answer for content that already passed: exposure crossing a threshold, a platform policy update, and complaints arriving.

You did it

You just designed an AI ad creative platform.

AdvertiserCreative APIVariant GeneratorBrand-Safety GateRights & LicensingBandit AllocatorPerformance MetricsPlatform Formatter
The finished design, end to end. · swipe to pan the diagram

Everything you assembled, in order

  • A single hand-designed creative is an untested guess — the platform's value is enabling real, data-driven testing at scale.
  • Variant generation aims for a good, diverse candidate pool, not a single predicted "best" creative.
  • The compliance gate fails closed given the asymmetric stakes — a policy violation can suspend an entire ad account.
  • Rights and licensing tracking is a distinct concern from content-policy compliance, covering commercial usage rights and likeness/trademark risk.
  • A bandit allocator continuously shifts spend toward better-performing variants, extracting more value than a fixed even A/B split.
  • A performance feedback loop lets the platform compound in quality over time, informed by what actually converted.
  • Approval and platform-specific formatting are separate concerns — approve once per concept, format many times per platform.
  • High-performing variants still need ongoing compliance re-checks, and generation cost is controlled by tiering expensive formats behind early cheap-format signal.

Where an interviewer pokes next

Getting the boxes right is the easy half. These are the questions that separate a candidate who drew the diagram from one who has run the thing. Answer each one out loud before you open it.

  1. How is this different from a general image-generation platform?

    A general image/text-to-image platform is focused on the MODEL-SERVING problem: prompt in, image out, reliably and at scale. This design assumes that capability exists and is entirely about the PRODUCT layer built specifically for advertising on top of it — generating many testable variants (not one image), a compliance gate whose stakes are specifically account-suspension risk, rights tracking for commercial ad use, and a bandit-driven spend-allocation system tied to real ad performance data. None of that is specific to image generation itself — it's specific to what advertising, as a domain, actually needs from generated creative.

  2. Why not just let advertisers manually pick their favorite variant instead of using a bandit allocator?

    Human intuition about which ad creative will perform best is notoriously unreliable — professional marketers are often surprised by which variant actually wins in real testing, precisely because real audience behavior doesn't always match confident predictions. A bandit allocator uses ACTUAL performance data, continuously, rather than a one-time subjective guess, and importantly keeps adapting if a variant's performance changes over time (ad fatigue, seasonal shifts) — a manual pick made once at the start can't react to any of that.

  3. Could rights/licensing tracking be automated entirely, or does it need human review?

    Some checks are genuinely automatable — verifying that a specific generation mode/model is licensed for commercial use is a lookup against known licensing terms, and automated likeness-detection (comparing a generated face against a database of recognizable public figures) can flag obvious cases. But genuinely ambiguous cases — does this generated design too closely resemble a specific trademark, is this a borderline likeness case — often still benefit from human legal review, especially for high-spend campaigns where the cost of getting it wrong is significant. A practical system typically automates the clear cases and routes ambiguous ones to human review, rather than claiming full automation covers every case.

  4. What happens if the bandit allocator concentrates spend on a variant that later gets flagged by the post-hoc compliance check?

    This is exactly the scenario the chaos scenario in Step 8 illustrates: the bandit allocator has been legitimately reallocating spend toward genuinely strong performance data, with no reason at that point to suspect a problem — the compliance issue is discovered SEPARATELY and LATER, through ongoing re-checking, not something the allocator itself could have anticipated from performance data alone. When that flag fires, the variant is pulled and the allocator redistributes its spend among the remaining approved variants — the two systems (performance allocation and compliance) operate on different signals and different timescales, and compliance always wins when the two disagree.

  5. Why generate cheap formats first rather than always generating every format for every initial variant?

    Video generation is meaningfully more expensive (in compute cost and generation time) than image and copy variants, and most initially-generated variants will NOT end up being the eventual winners — generating full video for all of them up front means paying that expensive cost on the majority that will be discarded once real performance data comes in. Tiered generation (cheap formats first, expensive formats only for early proven winners) means the expensive generation cost is spent almost exclusively on variants that have already demonstrated real promise, which is a much better return on the generation budget than generating everything for everyone up front.

Check yourself — the answers, and why

Nine steps in, these are the calls you should be able to make cold. Pick one, then read why.

  1. A single hand-designed ad creative is limited mainly because…

    Ad performance is measurable and depends on wording/imagery choices that are hard to predict without real testing.

  2. The Variant Generator produces many variants instead of one "best" guess because…

    The generator's job is a good candidate pool; determining the winner belongs to real-world testing.

  3. The Brand-Safety Gate fails closed (blocks publishing when unavailable) because…

    The asymmetric stakes make blocking publication the only defensible default during an outage.

  4. A bandit allocator differs from a fixed A/B split by…

    This extracts more value from the same total budget than waiting until a fixed test period ends to react.

  5. Rights and licensing tracking is necessary in addition to brand/policy checks because…

    Content can be perfectly policy-compliant while still carrying real commercial-licensing or likeness risk.

How you’d open this design in an interview

Before any boxes: agree what it must do, pin the qualities that shape everything, then build — naming each trade-off as you make it. The walkthrough above is that exact order.

What it must do

Agree on these before drawing a single box.

  • Generate variants: from one brief, produce many creative variants (headlines, images, CTAs) to test.
  • Comply: check every variant against brand guidelines and ad-platform policy before it goes live.
  • Track rights: verify each asset is licensed for commercial use and flag likeness/trademark risk.
  • Allocate budget: shift spend dynamically toward better-performing variants.
  • Format per channel: adapt approved creative into each platform’s required aspect ratios.

The qualities that shape everything

Each one names the mechanism that buys it.

Discover what actually converts
A Variant Generator programmatically produces many diverse variants from one brief for real A/B testing, not one predicted "best" guess.
One policy violation can’t suspend the whole account
The Brand-Safety Gate fails closed — no variant reaches a live ad platform while the gate is unavailable, even though generation continues.
Content-compliant isn’t the same as legally usable
A separate Rights & Licensing tracker verifies commercial-use licensing and flags likeness/trademark risk, distinct from content-policy checks.
Extract more value from the same budget
A Bandit Allocator continuously shifts spend toward stronger performers instead of a fixed even A/B split.
The platform compounds in quality over time
A performance feedback loop biases future generation toward the style/attribute patterns that actually converted.
A winning variant is still safe
Ongoing compliance re-checks run on live high performers — a metric win doesn’t override a compliance failure discovered later.

The trade-offs you say out loud

Senior signal isn’t the boxes — it’s naming what you gave up and why it was the right price.

Many testable variants over one best-guess creative

No generation process can reliably predict ad performance in advance; a single output gives advertisers nothing to test against, defeating the empirical value.

Fail closed on compliance over publishing while the gate is down

A single policy-violating ad can suspend the entire ad account — a cost wildly disproportionate to whatever delay a brief compliance-check outage causes.

Separate rights tracking over trusting content-policy checks to cover everything

A perfectly policy-compliant asset can still be unlicensed for commercial use or resemble a real person; rights is a distinct legal axis of risk.

Bandit allocation over a fixed even A/B split

A fixed split spends real budget on clearly-losing variants for the whole test window; a bandit reallocates toward winners continuously, extracting more from the same budget.

Ongoing re-checks on winners over a one-time gate at generation

A variant can start reading as manipulative or attract complaints only once seen widely; a metric win doesn’t exempt it from a later compliance failure.

The answer, out loud

What a strong answer to “Design an AI Ad Creative Platform” sounds like, first question to last trade-off. It is about 7 minutes of talking; the whiteboard and the interviewer fill the rest of the 45. Read it aloud once, then close the page and give it yourself.

  1. 0–4 min

    What is actually hard here

    Let me say what the problem actually is. Generating one good-looking ad image is solved — I plug into an image model. The difficulty is the system around the model: what to generate, what may run, and who pays when that call is wrong. I need variants a real audience can separate, certainty about what reaches a live platform — the penalty lands on the whole account, not the one ad — assets that are legally usable in a paid ad, and performance data coming back to change what gets generated next. So I would build the product layer on top of a generative model, not another way to serve one.

  2. 4–9 min

    Start from the baseline and its real flaw

    The simplest version is a designer making one creative per campaign, and I want to be precise about why that is limited. It is not that one creative takes too long to produce. It is that it is an untested guess, and ad performance depends on wording, imagery and the call-to-action in ways nobody predicts reliably up front. Advertising is one of the few creative domains where good is directly measurable — clicks, conversions — so the opportunity is producing enough tested alternatives that data, not intuition alone, decides what works.

    Built in step 1: One hand-designed creative per campaign
  3. 9–14 min

    Generate a candidate pool, not a winner

    So the first component is a Variant Generator: one brief in, many variants out — different headlines, different images, different calls-to-action. I would be precise about its job. It is not trying to pick the winner, because no generation process predicts real-world ad performance reliably. Its job is a good, diverse candidate pool, and the winner is determined empirically, by real audiences. I also would not make this opt-in. If an advertiser has to specifically ask for more than one variant, I have turned the core value of the product into an extra.

    Built in step 2: Many variants, not one "best" guess
  4. 14–20 min

    The gate that fails closed

    Now the highest-stakes piece. Every variant goes through a Brand-Safety Gate that checks it against the brand’s own guidelines and against ad-platform policy before it can go live. The question I would expect is what happens when that gate is down, and my answer is that it fails closed — generation and drafting carry on, publishing stops. The reasoning is the asymmetry. On one side, a brief delay to one campaign. On the other, a single policy-violating ad suspending the entire account, which takes down every campaign that account runs. Sampling does not help either: partial checking is not meaningfully safer when one miss carries that cost.

    Built in step 3: One violation can suspend the whole account
  5. 20–25 min

    Rights is a separate question

    Then a Rights and Licensing tracker, separate from the gate on purpose. Brand and policy checks ask whether the content is appropriate to show. Rights asks a legal question about the asset itself: does the licence covering this generation extend to a paid ad, does a generated face resemble a real identifiable person, does a design echo a trademark. A variant can pass every content check and still carry all of that. Folded together, I end up with one green light that hides a legal risk behind a content pass.

    Built in step 4: Generated doesn't automatically mean usable
  6. 25–31 min

    Spend while you are still learning

    Approved variants need budget, and the default here — an even split for a fixed window — is the part I would push back on. So, a bandit allocator, and I would name what it costs me. An even split buys a clean comparison; every variant gets the same shot, so the final number means something. A bandit breaks that deliberately: it starves the arms it doubts, which is the point, but it measures them thinly too, so I can no longer say how much worse they were. That is right when a campaign has to sell and wrong when it has to teach me about this account — a choice on the campaign, not a platform default.

    Built in step 5: Beyond a fixed A/B split
  7. 31–37 min

    Close the loop, then ship the shapes

    Two things finish the main path. First, performance metrics feed back into generation — not retraining the model per campaign, but letting the styles that converted bias what gets generated next. Without it the platform is no better on an advertiser’s fifth campaign than on their first. Second, a Platform Formatter adapts approved creative into each channel’s shapes — vertical for Stories, wide for display, square for feed. I would be careful what the approval attaches to: the elements the gate looked at, not the file. A reshape that carries them all across is the same creative and clears for nothing; one that drops or moves something is new and pays full price.

    Built in step 6: Learn from what actually converted
  8. 37–43 min

    The unhappy paths

    Finally, the sharp edges. A variant can be winning and still read as manipulative once more people see it, so checking cannot stop at generation. I would build in a precedence rule rather than a conversation: a compliance flag outranks the allocator’s evidence, settled once in code, so nobody argues it while the variant still earns. I would expect that to be unpopular: the money it stops is visible, the risk it avoids is not. The other pressure is cost, so I would tier generation — cheap formats first, video once a variant has earned it. The catch is that promotion runs on the thinnest data in the system, so I would promote a small set, not one early leader.

    Built in step 8: Winning isn't the same as safe, and generation isn't free
  9. 43–45 min

    The trade-off, and what I would do next

    So the trade-off running through this is speed against safety, and I have deliberately taken safety at the two points where the downside is uncapped: publishing stops when the gate is down, and a winner gets pulled when a re-check flags it. Both cost advertisers real time and real money, and I would expect to defend both. With more time, I would go at rights automation — which cases are a licensing lookup the system can settle alone, which genuinely need human legal review, and how to route between them without making every high-spend campaign wait on a lawyer.

What this teaches

Learn AI system design by building a platform that generates ad creative — images, copy, and video variants — at scale for advertisers, built ON TOP of generative models rather than serving them directly. An interactive guide covering why one hand-designed creative can't be tested at scale, programmatic variant generation, a brand-safety and ad-platform-policy compliance gate that fails closed (a violation can get an entire ad account suspended), rights and commercial-licensing tracking, dynamic multi-armed-bandit budget allocation instead of a fixed A/B split, a performance feedback loop, and tiered generation cost control.

Key takeaways

  • A single hand-designed creative is an untested guess — the platform's value is enabling real, data-driven testing at scale.
  • Variant generation aims for a good, diverse candidate pool, not a single predicted "best" creative.
  • The compliance gate fails closed given the asymmetric stakes — a policy violation can suspend an entire ad account.
  • Rights and licensing tracking is a distinct concern from content-policy compliance, covering commercial usage rights and likeness/trademark risk.
  • A bandit allocator continuously shifts spend toward better-performing variants, extracting more value than a fixed even A/B split.
  • A performance feedback loop lets the platform compound in quality over time, informed by what actually converted.
  • Approval and platform-specific formatting are separate concerns — approve once per concept, format many times per platform.
  • High-performing variants still need ongoing compliance re-checks, and generation cost is controlled by tiering expensive formats behind early cheap-format signal.

Concepts covered

  • A platform built ON generative models, not just serving them
  • One hand-designed creative per campaign
  • Many variants, not one "best" guess
  • One violation can suspend the whole account
  • Generated doesn't automatically mean usable
  • Beyond a fixed A/B split
  • Learn from what actually converted
  • One approved creative, many required shapes
  • Winning isn't the same as safe, and generation isn't free
RUN IT YOURSELF

The impressions an even split keeps buying after it knows

Step 5's argument, run for real in your browser: four approved creatives with fixed, hidden click rates, allocated two ways over the same 12,000 impressions — a fixed even A/B split, and a Thompson-sampling bandit. It prints clicks, regret, and the impressions the even split still spends on a creative its own data has already ruled out. Raise RATES["D"] from 0.020 toward the others, hit Run, and watch that number — and most of the bandit's lead — go with it.

HOW TO READ THE CODE — 5 IDEAS
  1. The headline pair reads the same pre-drawn outcome streams, so the gap between them is the allocation rule and not luck — the n-th impression on a creative is the same coin flip whoever buys it.
  2. A creative is only ruled out when its whole 95% interval sits below the leader's. Being behind is noise; separation is evidence, and the rule has to hold three checks running.
  3. The even split never acts on that verdict: it is round-robin, so it keeps buying a quarter of everything until the window ends (step 5 — "spends real budget on clearly-losing variants for the ENTIRE test duration").
  4. When the rejection point lands is wildly noisy — the middle 80% of 301 redraws span a factor of six — but the quantity that costs money is (HORIZON − t) / 4, and that band is only ~32% wide. The waste survives the noise the verdict does not.
  5. Strike the bad creative and rerun the pair over fresh campaigns: the bandit still leads, but by single digits in roughly three campaigns out of four instead of 89 clicks every time. A bandit is worth its cost when one option is genuinely bad, and the saving is paid for in measurement — the starved creative's interval is two to three times wider.
CPython · WebAssembly
built so a winning-but-manipulative variant gets pulled before it costs the account — make the calls, spike a compliance flag, run the gauntlet.
Finished this one? 0 / 65 AI System Designs done
NextDesign a Support Resolution Agent Closest AI system design to this one

Explore the topic

See this alongside everything else on the same subject — handbooks, system designs, challenges and tools, in one place.

More AI System Designs