A GAN generates an image in a single forward pass — milliseconds. A diffusion model produces the same image by running a denoising loop dozens of times, turning that millisecond operation into a multi-second, GPU-bound one. Treat the two as interchangeable inference services and you inherit latency SLAs you cannot meet and compute bills nobody forecast. That is the mistake we see most often in generative deployments. A team picks a model on quality grounds, wraps it in a REST endpoint, points an autoscaler at CPU utilisation, and assumes the serving layer is a solved problem. It is not. The serving layer is where the architecture of the model reaches into your infrastructure and rewrites your cost and latency profile. System design has to follow from the architecture — not precede it. What does MLOps system design mean when the model is generative? MLOps system design is the set of decisions that turn a trained model into a service that meets a contract: how you package it, where it runs, how it scales, how you batch requests, how you cache, how you monitor drift, and how you roll new versions out safely. For a classifier or an embedding model, most of these decisions are close to architecture-agnostic — the inference cost is a single, predictable forward pass, so the pipeline looks the same whether you serve a ResNet or a BERT encoder. Generative models break that assumption at exactly one point: the inference loop. A generative adversarial network (GAN) maps a latent vector to an output in one pass through the generator. A diffusion model — Stable Diffusion, or any DDPM-style sampler — starts from noise and refines it over many denoising steps, each of which is a full forward pass through a U-Net or transformer backbone. The quality that makes diffusion attractive comes precisely from that iterative refinement, and the iteration is what your infrastructure has to absorb. The general discipline still applies. If you want the architecture-agnostic foundation — versioning, reproducibility, monitoring, CI for models — start with what MLOps principles mean in practice for generative AI teams. This article is about the part that is not agnostic: the serving mechanics that flip depending on whether the generator runs once or fifty times per request. You can read the broader deployment context on our generative AI practice page. How does GAN versus diffusion change the serving architecture? The divergence is the inference loop, and everything downstream inherits from it. A GAN’s forward pass is typically on the order of milliseconds on a modern GPU for common image resolutions (approximate, and highly dependent on resolution and generator depth). Because inference is a single kernel sequence, you can batch aggressively, autoscale on request rate, and hit interactive latency budgets without special engineering. The serving profile resembles a heavy classifier. A diffusion model changes the arithmetic. If a single denoising step costs roughly the same as one GAN forward pass, and the sampler runs 20 to 50 steps, total latency lands in the multi-second range for a single sample — and the GPU is occupied for that entire window (observed pattern across image-generation deployments; the exact figure depends on sampler, step count, and resolution). That single fact cascades: Latency budgets — a real-time or interactive SLA that a GAN clears trivially may be structurally unreachable for a naïve diffusion deployment. Autoscaling triggers — CPU utilisation is meaningless; the binding resource is GPU-seconds per request, and scaling has to key off queue depth and GPU occupancy. Batching windows — you cannot hide multi-second inference behind small batch waits; batch economics and latency pull in opposite directions. Hardware sizing — a GAN pool sized for throughput will be catastrophically undersized for diffusion at the same request rate. This is a concrete instance of the general truth that hardware choice follows from workload profile, which we unpack in choosing the best MLOps platform for agentic and generative workloads. Decision table: serving profile by architecture Dimension GAN (single forward pass) Diffusion (iterative denoising) Inference cost One forward pass (~ms, resolution-dependent) N steps × forward pass (~seconds) GPU occupancy per request Short burst Sustained for full sampling loop Autoscaling signal Request rate / CPU proxy works GPU-seconds, queue depth, occupancy Batching Aggressive, low latency cost Constrained — latency vs. throughput tension Realistic latency SLA Interactive / near-real-time Seconds; needs distillation or async Dominant cost driver GPU throughput GPU-seconds × step count First lever when over budget Larger pool / bigger batch Reduce steps, distil, or cache The table is the whole argument in compressed form: the same request, the same output modality, two entirely different infrastructures. Why does diffusion sampling break latency SLAs, and how do you design around it? The reason is not that diffusion is slow in some vague sense. It is that latency scales linearly with step count, and step count is a quality knob you usually cannot turn to zero. A GAN’s latency is fixed by its architecture; a diffusion model’s latency is a product you partly control and partly inherit from the quality bar. Designing around it means accepting that you have three families of levers, and each trades something away: Reduce the loop. Fewer sampling steps cut latency proportionally, but below a threshold quality degrades visibly. Distilled diffusion models — progressive distillation, consistency models, and similar approaches — compress the loop into a handful of steps (sometimes one) by training a student to reproduce the teacher’s trajectory. The catch is that distillation is another training and validation effort, and the distilled model is a distinct artifact you have to version and monitor. Absorb the loop asynchronously. If the product tolerates it, move generation off the request path entirely: accept the request, return a job id, run the sampling loop in a worker pool, and deliver the result via callback or poll. This is the single most reliable way to stop diffusion latency from breaking a synchronous SLA, because it changes the contract instead of fighting the physics. Cache the loop. Where inputs repeat or share structure, cache intermediate or final outputs. Latent caching and prompt-level result caching only help when your traffic actually repeats — measure the hit rate before you build the cache, because a cache with a low hit rate is pure operational overhead. The runtime matters here too. Compiling the U-Net backbone with torch.compile, exporting to TensorRT, or fusing attention kernels with FlashAttention attacks the per-step cost rather than the step count — a smaller, multiplicative win, but it stacks with step reduction. None of these change the fundamental shape: diffusion is GPU-bound for a sustained window, and your system has to be designed for that window, not against it. How should GPU pools, batching, and autoscaling differ? Start from the resource that is actually scarce. For a GAN, GPU throughput is the constraint and you scale the pool to hold request rate under the throughput ceiling. For diffusion, GPU-seconds are the constraint: each request consumes a multi-second block of a device, so the pool has to be sized against concurrent sampling loops in flight, not requests per second. Batching diverges just as sharply. A GAN benefits from large batches with negligible latency cost — you gather requests for a few milliseconds and dispatch them together. A diffusion server batching the same way pays the batch-formation delay on top of multi-second inference, and worse, a large batch holds the whole batch hostage to the slowest sampling schedule in it. Continuous batching — the pattern that dynamic-batching servers like NVIDIA Triton support — helps by letting requests enter and leave the batch across steps, but you still tune the window against the loop, not against a millisecond-scale forward pass. Autoscaling on the wrong signal is the failure that produces surprise bills. If your autoscaler watches CPU, a diffusion service will look idle while the GPUs are saturated, so it will not scale until the queue has already blown past the SLA. Key the autoscaler off GPU occupancy and queue depth, and give it lead time — spinning up a GPU node and loading a multi-gigabyte model is not instantaneous, and diffusion queues build faster than the scale-out completes. For the observability side of this — knowing when the profile you designed for has drifted — see monitoring ML models in production for image-gen stacks. Forecasting per-generation compute cost before launch The cost model for a generative service is not “cost per request” in the abstract; it is GPU-seconds per generation multiplied by the price of the GPU-second. For a GAN, GPU-seconds per generation is small and roughly fixed. For diffusion, it is step count × per-step time, and you can compute a defensible estimate before you deploy: Worked estimate (illustrative — plug in your measured numbers). Suppose one denoising step measures 40 ms on your target GPU at your resolution, and your quality bar needs 30 steps. That is 1.2 GPU-seconds per generation before batching. At an on-demand GPU price of, say, $2/hour ($0.00056/GPU-second), a single generation costs about $0.00067 in raw GPU time — before overhead, retries, and idle. Ten million generations a month is roughly $6,700 in GPU-seconds alone. Halve the steps via distillation and you halve that line. Batching four requests per device with good occupancy divides the per-generation device cost again. Every number here is a placeholder; the structure is what you forecast. The point of writing this down before launch is that it makes the levers explicit and quantified. Distillation is worth its added complexity precisely when the step-count reduction pays back the training and versioning cost across your generation volume — which is a number you can compute, not a judgement call. The same discipline for edge-constrained targets is covered in model optimization for edge inference. FAQ How does mlops system design work in practice? MLOps system design is the set of decisions that turn a trained model into a service meeting a contract: packaging, placement, scaling, batching, caching, monitoring, and safe rollout. For most models these decisions are close to architecture-agnostic because inference is a single predictable forward pass. Generative models break that at the inference loop, so the design has to follow from the model’s actual inference profile rather than a generic template. How does the choice between a GAN and a diffusion model change the serving and inference architecture? A GAN generates in one forward pass, so it batches aggressively, scales on request rate, and hits interactive latency easily — its serving profile resembles a heavy classifier. A diffusion model runs a denoising loop over many steps, occupying a GPU for a sustained multi-second window per request. That single difference cascades into autoscaling signals, batching economics, hardware sizing, and achievable latency SLAs. Why does diffusion model iterative sampling break latency SLAs that GANs meet easily, and how do you design around it? Diffusion latency scales linearly with step count, and step count is a quality knob you usually cannot turn to zero, whereas a GAN’s latency is fixed by its architecture. You design around it with three lever families: reduce the loop (fewer steps, distilled diffusion), absorb it asynchronously (job-and-callback instead of synchronous requests), or cache repeated work. Runtime compilation with torch.compile or TensorRT attacks per-step cost as a stacking, smaller win. How should GPU pool sizing, batching, and autoscaling differ between GAN and diffusion deployments? Size a GAN pool against request rate under a throughput ceiling; size a diffusion pool against concurrent sampling loops in flight, because GPU-seconds are the scarce resource. Batch a GAN aggressively at negligible latency cost, but batch diffusion with continuous-batching techniques that let requests enter and leave across steps. Autoscale diffusion on GPU occupancy and queue depth — never CPU, which reads idle while GPUs saturate — and give the scaler lead time for node startup and model load. What per-generation compute cost trade-offs does the architecture impose, and how do you forecast them before launch? The cost is GPU-seconds per generation times the price of a GPU-second; for diffusion that is step count multiplied by per-step time. You can compute a defensible pre-launch estimate from a measured per-step time, your quality-driven step count, the GPU price, and expected batch occupancy. Writing it down makes the levers explicit and turns the distillation-versus-complexity question into a number rather than a judgement call. Which parts of an MLOps pipeline are architecture-agnostic, and which must follow from the model’s inference profile? Versioning, reproducibility, drift monitoring, CI for models, and rollout safety are largely architecture-agnostic and apply to any generative model. Serving mechanics — batching strategy, autoscaling signal, GPU pool sizing, caching, and the latency contract itself — must follow from whether the model runs once or many times per request. Design the agnostic layer once; derive the serving layer from the measured inference profile. When do techniques like distilled diffusion or caching justify their added system complexity in production? Distilled diffusion justifies its extra training and versioning cost when the step-count reduction pays back across your generation volume — a number you compute from the cost model, not a reflex. Caching justifies itself only when traffic actually repeats enough to earn a high hit rate; measure the hit rate before building it. Both are worth it precisely when the forecasted GPU-second savings exceed the operational overhead they add. Where this leaves the design decision The uncomfortable part is that the architecture choice and the serving design are not two decisions — they are one, made in the wrong order most of the time. A model selected purely on output quality can arrive at the serving layer carrying a latency profile that no amount of infrastructure engineering will rescue, because the physics of a fifty-step loop does not negotiate. That is why serving and deployment constraints belong upstream, as an input to the GenAI feasibility assessment rather than a problem discovered after launch. The question worth asking before you commit is not “which model produces the best output” but “which model produces an acceptable output within a latency and cost envelope my infrastructure can actually hold” — and you can only answer that by measuring the inference loop before you build the pipeline around it.