Cloud Compute Options and Trade-offs Questions
Choosing among compute abstractions independent of provider: virtual machines, containers, managed container services, serverless functions, and bare metal. Covers the cost, control, cold-start, scaling, and operational trade-offs of each model; how to pick an instance family or hardware accelerator (general-purpose, compute-optimized, memory-optimized, GPU, TPU) and a purchasing model (on-demand, reserved, spot); and how workload characteristics (latency, statefulness, burstiness) drive the decision. Managed-versus-self-managed reasoning lives here.
Define cold start in the context of serverless function platforms. What causes a cold start, how does it affect user-facing latency, and what mitigation techniques are available? Discuss the cost and complexity trade-offs of those mitigations, and how cold-start behavior can differ across cloud providers' FaaS offerings.
Sample Answer
Direct answer
A cold start is the extra latency a serverless function pays on the first invocation of a brand-new execution environment: the platform has to provision compute, initialize the language runtime, load your code and its dependencies, and run any top-level initialization before it can execute your handler at all, on top of the handler's own execution time. A warm invocation reuses an already-initialized environment and skips all of that.
Causes, effect, and mitigation
Causes. Environment provisioning: allocating compute for a brand-new instance. Runtime bootstrap: starting the language runtime, which is why a lighter-weight runtime tends to cold-start faster than a heavier one, and why a larger deployment package with more dependencies makes bootstrap slower. Your own top-level initialization code: creating a database connection pool or loading a large configuration or model into memory, which reruns on every cold start unless it's deliberately made reusable.
Effect on latency. Cold starts add a one-time tax to whichever request happens to land on a new instance. This hurts most on low-traffic functions, where instances scale down between requests and every burst starts cold, and on sudden traffic spikes, where concurrency has to expand faster than warm instances exist to absorb it, so a cluster of requests can all pay the cold-start tax at once.
Mitigation techniques. Keeping a baseline of pre-warmed or provisioned instances so some fraction of traffic never hits a cold path. Shrinking the deployment package and trimming unused dependencies so bootstrap does less work. Choosing a lighter-weight runtime for latency-critical functions. Deferring expensive initialization until it's actually needed, so a cold start's fixed cost is smaller. At the architecture level, routing latency-critical paths to always-on containers instead of scale-to-zero functions entirely.
Cost and complexity trade-offs of those mitigations. Pre-warming or provisioned capacity converts scale-to-zero's near-zero idle cost into a standing cost proportional to the warm baseline you pay for, cutting directly into serverless's main cost advantage. It also adds an operational knob (how much to keep warm, and re-tuning it as traffic shifts) that a pure "just deploy the function" model doesn't have. Trimming dependencies and deferring initialization are close to free in dollar terms but add engineering discipline, since the benefit can silently erode as new dependencies get added over time without anyone revisiting the bundle size. Moving latency-critical paths to containers eliminates cold starts there entirely, at the cost of giving up serverless's operational simplicity for that path.
How this differs across providers, qualitatively. Providers differ in the mechanisms they expose (a dedicated provisioned-concurrency feature versus tunable idle-timeout behavior), in how heavily the choice of language runtime affects bootstrap time on that specific platform, and in whether attaching a function to a private network adds its own cold-start latency. Because the specifics and their exact magnitude are provider- and release-specific, validate actual behavior against the target platform's current documentation and your own load test, rather than assuming one provider's characteristics carry over to another.
Trade-offs and pitfalls
The most common measurement mistake is looking only at average latency, which hides cold starts entirely, since they show up in tail latency. Always look at percentile latency and the ratio of cold to warm invocations, not the mean. A second pitfall is adding provisioned concurrency and never sizing it back down as traffic changes, quietly paying container-like standing cost while still carrying serverless's other constraints, such as execution-time limits and forced statelessness. Measure your own cold-to-warm invocation ratio in production before investing in mitigation at all, since a function invoked constantly may rarely cold-start regardless of platform.
You manage a large compute fleet that includes on-demand, reserved, and spot instances. Describe a purchasing and capacity strategy that minimizes cost while meeting availability SLAs: how you'd size reservation commitments, plan buffer capacity, automate spot diversification, and handle spot interruptions with a graceful fallback to on-demand or reserved capacity.
Sample Answer
Direct answer
Size reserved or committed capacity to the fleet's sustained minimum load, never the average or the peak. Fill the elastic band above that minimum primarily with diversified spot capacity. Keep a smaller on-demand buffer as the fallback that absorbs both spot interruptions and any capacity spot can't fill fast enough. Automate the fallback path so an interruption is a routine, tested event rather than an incident.
Building the strategy
Sizing reservation commitments. Look at the fleet's load distribution over a representative window, weeks to months, capturing weekly and seasonal cycles, and reserve at a low percentile of that distribution, such as the tenth percentile: the load level the fleet is at or above roughly 90 percent of the time. Reserving above the actual floor means paying for committed capacity that sits idle whenever load dips; reserving below the floor means the "guaranteed" baseline isn't actually guaranteed.
Buffer capacity. Size the on-demand buffer to the worst-case simultaneous loss scenario: the largest plausible number of spot instances that could be reclaimed together, since a whole spot pool or availability zone can be reclaimed at once during a demand spike from other customers, plus normal traffic-growth headroom. Provision this buffer as capacity you can call on quickly, not capacity that has to be requested and provisioned cold.
Spot diversification. Spread spot capacity across multiple instance types and multiple availability zones, or regions where latency allows, rather than one type in one zone, because spot reclaim events correlate within a single pool. A diversified fleet lets the autoscaler shift into a still-available pool instead of losing the whole spot allocation at once. Automate this as a standing policy across a defined set of interchangeable instance types, not a manual choice revisited occasionally.
Handling interruptions gracefully. Consume the interruption warning most spot platforms provide before reclaiming an instance, to drain in-flight work and deregister it from the load balancer before it disappears, rather than discovering the loss only when health checks fail. Set the autoscaler's fallback order to try the diversified spot pool first and the on-demand buffer second, so a failed spot replacement automatically falls back to on-demand instead of leaving the fleet under capacity.
Worked example
Suppose the fleet's load distribution over the last quarter shows a floor of 70 concurrent instances (the tenth percentile), a mean of 100, and a peak of 160. Reserve 70 instances to cover the floor. Cover the elastic band above the 70-instance reservation, 90 instances up to the 160-instance peak, primarily with diversified spot, keeping an on-demand buffer sized to the worst simultaneous spot loss the team is willing to plan for, here 20 percent of that 90-instance elastic band, or 18 instances, with the remaining 72 instances filled by diversified spot. Using illustrative relative unit-price ratios of 0.6 for reserved, 0.35 for spot, and 1.0 for on-demand, each per instance-hour:
Costblended, at peak=70(0.6)+72(0.35)+18(1.0)=42+25.2+18=85.2 unit-hoursagainst an all-on-demand fleet at the same 160-instance peak:
Costall on-demand, at peak=160(1.0)=160 unit-hoursThat's a reduction of 1−85.2/160=0.4675, or 46.75 percent, at peak load alone, before counting that the 70 reserved instances are also cheaper than on-demand around the clock, at every load level, not just at peak. The exact savings depend on real price ratios and the real load distribution; the method, reserving the floor, diversifying the elastic band on spot, and sizing the on-demand buffer to the worst tolerable simultaneous loss, is what transfers.
Trade-offs and pitfalls
The most damaging pitfall is reserving to the mean instead of the floor, which either strands the team paying for unused reserved capacity during low-traffic periods, or under-reserves relative to what's actually needed as a guaranteed baseline. Always reserve to a load percentile checked against real data, not intuition. A second pitfall is treating spot diversification as a one-time setup; instance-type availability and pricing shift over time, so the diversified pool needs periodic review. A third is sizing the on-demand fallback buffer only for one spot instance disappearing, rather than a correlated pool-wide reclaim event; test the fallback path with a real simulated interruption before trusting it in an actual incident.
An organization runs both machine learning model training and online inference. Training needs many GPUs for throughput; inference needs low latency per request. Compare the compute options available for each workload, and recommend configurations that balance cost, latency, and operational complexity for both.
Sample Answer
Direct answer
Training and inference are different workloads that should usually run on different compute, sized for different bottlenecks. Training wants maximum sustained throughput across many accelerators, with tolerance for job-level restarts, while online inference wants low, predictable per-request latency with enough headroom to autoscale to traffic. A right-sized training cluster and a right-sized inference fleet are not the same purchase, even when they serve the same model.
Compute options by workload
Training. Characteristics: long-running batch jobs, where accelerator memory capacity and interconnect bandwidth (how fast accelerators can exchange data with each other) matter as much as raw accelerator count, since multi-accelerator jobs need fast accelerator-to-accelerator communication, not just many chips. Training jobs can usually tolerate preemption if checkpointing is solid, and cost is dominated by total accelerator-hours. Compute options: large multi-GPU instances (graphics processing units, now the general workhorse for parallel numeric computation) or accelerator pods purchased on spot or preemptible pricing (much cheaper capacity the provider can reclaim with short notice) where checkpointing exists, since training's restart tolerance makes it a good fit for interruptible capacity, plus a reserved or committed baseline if training runs nearly continuously.
Online inference. Characteristics: short per-request compute, where tail latency (the slow end of the response-time distribution, not the average) matters more than raw throughput per accelerator, unpredictable request volume that needs to scale quickly, and a workload that typically runs constantly, so it can't be fully spot-based without a fallback, since interruption directly hurts a live user. Compute options: smaller GPU-backed instances, or CPU-only if the model is small enough, behind an autoscaled fleet (containers on an orchestrated platform are the common shape, since they give fast, controlled autoscaling), with a reserved baseline for steady traffic plus on-demand burst capacity, and serving-time optimizations (batching requests together, quantizing the model to shrink it) to make a smaller, cheaper accelerator tier viable.
Worked example
For training, use spot or preemptible multi-GPU nodes for the bulk of the epochs, checkpointing every few minutes so a preemption loses at most that much progress, and keep a small on-demand fallback reserved for the final convergence run, where an uninterrupted window is worth paying for directly. For inference, keep a minimum of two always-on GPU instances as a high-availability floor, autoscale further on a p95-latency or queue-depth metric, and enable request batching up to a batching-latency budget small enough that it doesn't push the response past the target p95.
Trade-offs and pitfalls
A common wrong turn is sizing the inference fleet the way the training cluster was sized (fewer, bigger, less redundant instances) because "that's what worked for training." That trades away exactly the failover redundancy inference needs. Another is running training jobs on capacity reserved for inference "since it's free at night," which only works with strong isolation; a runaway training job must not be able to starve inference of accelerators during a traffic spike. Recommend explicit, separate capacity pools for the two workloads rather than one shared pool governed by priority rules you hope hold under pressure.
Design a compute strategy for an e-commerce platform expected to handle 10,000 requests per second at peak with seasonal spikes, PCI compliance requirements for card processing, and a mix of stateful and stateless services, run by a small operations team. Decide which components should run on VMs, containers, a managed PaaS, or serverless, and justify your choices across scale, compliance, cost, and operational burden.
Sample Answer
Direct answer
I'd split this by component rather than pick one compute model for the whole platform: the storefront and browsing API on a managed container service for scale and fast rollback under seasonal load, the payment-processing path isolated onto its own tightly-scoped, PCI DSS (Payment Card Industry Data Security Standard, the compliance framework for handling card data) compliant service boundary rather than sharing infrastructure with the rest of the app, stateful services (cart, session, inventory reservation) on containers with persistent storage rather than anything that scales to zero, and background and reporting work on serverless or a managed batch service. For a small operations team, every one of those choices should lean toward the most managed option that still meets the constraint, not the most controllable one.
Structured elaboration
flowchart TB
subgraph Edge
CDN[Content delivery network]
end
subgraph Storefront["Storefront and API tier"]
WEB[Managed container service<br/>autoscaled, stateless]
end
subgraph Stateful["Stateful services"]
CART[Cart and session store<br/>containers, persistent volumes]
INV[Inventory reservation<br/>containers, persistent volumes]
end
subgraph PCI["PCI-scoped boundary"]
PAY[Payment processing<br/>isolated network segment,<br/>tokenization via payment gateway]
end
subgraph Async["Background work"]
BATCH[Reporting and nightly jobs<br/>managed batch or serverless]
end
CDN --> WEB
WEB --> CART
WEB --> INV
WEB -->|tokenized request only| PAY
WEB --> BATCH
- Storefront/browsing/API tier (stateless, must absorb 10,000 requests/second peak with seasonal spikes): managed container service. This is squarely the "bursty but not adversarially unpredictable" profile a managed autoscaler is built for, seasonal spikes are forecastable enough to pre-scale ahead of a known sale event, and it avoids the ops burden of running a control plane, which a small team can't staff.
- Payment processing (PCI compliance): the single highest-leverage decision here is minimizing PCI scope, not choosing a compute model for it. Route actual card data through a PCI-compliant payment gateway that returns a token, so raw card numbers never touch your own compute at all; whatever thin service you run to call that gateway sits in its own network segment with the tightest possible IAM (identity and access management) and network controls, on containers, not shared infrastructure with the storefront, so a compromise elsewhere in the platform can't reach the compliance boundary.
- Stateful services (cart, session, inventory reservation): containers with persistent storage, not serverless. These need to hold state across requests (a shopping cart mid-checkout, a reserved-but-not-yet-purchased inventory unit) and serverless's stateless, scale-to-zero model actively fights that; a lost or duplicated cart state is a customer-visible bug, not just a performance hit.
- Background and reporting (nightly settlement reports, catalog re-indexing): serverless or a managed batch service. This work is off the critical path, has no user-facing latency requirement, and benefits the most from near-zero idle cost.
Worked example
During a seasonal spike (a flash sale), the storefront tier needs to scale from a baseline of, say, 500 requests/second to the stated 10,000 requests/second peak. A managed container service with autoscaling configured against a known upcoming sale date lets the team pre-scale ahead of the event (avoiding autoscaler reaction lag right when it matters most) and scale back down afterward, paying the container premium only for the duration of the event. The PCI-scoped payment path deliberately does not scale with the storefront's raw request volume, since most storefront traffic is browsing, not checkout; sizing it to actual checkout throughput (a much smaller number) keeps the compliance boundary small and auditable, which is exactly the point of scoping it separately in the first place.
Trade-offs and pitfalls
- Cost: isolating the PCI boundary costs more per unit of throughput (a dedicated, tightly-controlled service is never the cheapest option) but that's the correct trade against compliance risk; trying to save money by sharing infrastructure between the storefront and payment path massively expands your PCI audit scope and the cost of every future security review.
- Operational burden for a small team: the single biggest risk in this design is the temptation to run the whole thing on self-managed Kubernetes for uniformity. A small team should resist that; the managed container service costs more per unit of compute but removes control-plane operations, node patching, and upgrade coordination entirely, which is the actual scarce resource here.
- Common wrong turn: recommending "everything serverless" for seasonal e-commerce because serverless is good at bursty traffic. It's a good fit for the storefront's read-heavy browsing traffic, but a poor fit for cart/session state and actively wrong for a compliance boundary where you want maximum control over exactly where card data can and cannot go.
- What would flip a piece of this: if the team later hires dedicated platform engineers, moving the storefront tier onto self-managed Kubernetes could reclaim cost and control, but that trade only pays off once the team can actually staff it, which explicitly isn't the case here.
Your platform needs to run video-transcoding jobs that frequently take longer than 15 minutes, but the rest of the platform uses serverless functions and serverless execution-time limits make that impossible for these jobs. Outline an architecture for the long-running jobs, and explain how you'd handle retries and idempotency so a failed job doesn't corrupt or duplicate output.
Sample Answer
Direct answer
Video transcoding at over 15 minutes needs to move off the request/response serverless model entirely and onto a queue-driven worker architecture: a durable message queue holds one job per video (or per chunk of a video), and a pool of long-running workers, on containers or virtual machines, not functions, pulls jobs and processes them for as long as they take. The rest of the platform can stay serverless; only the small set of genuinely long-running steps needs to escape the time limit, and the two coexist fine as long as the handoff between them is a durable queue, not a direct synchronous call.
Structured elaboration
- Job intake: a lightweight serverless function still handles the upload trigger and enqueues a transcoding job, since that part genuinely is a fast, stateless operation well suited to serverless.
- Worker pool: a pool of containers (on a managed container service, sized to autoscale on queue depth rather than request rate) or a managed batch service consumes jobs from the queue with no execution-time ceiling, running each transcode to completion.
- A second pattern for the same underlying problem: for workflows that aren't one long computation but a sequence of steps that together exceed serverless limits, some with occasional multi-hour waits or even a human-approval gate in the middle (a manual review before publishing a transcoded video, for example), a durable-workflow orchestration service is often a better fit than a single long-running worker: it coordinates a chain of short function calls, each individually within the serverless time limit, and can pause indefinitely between them (including waiting on a human action) without holding a worker process idle the whole time. Video transcoding and a human-approval publishing workflow are two different shapes of the same "beyond serverless time limits" problem, and it's worth being able to name both.
Handling retries and idempotency so a failed job doesn't corrupt or duplicate output:
- Idempotency key: each job carries a unique, deterministic identifier (derived from the input video and a version of the transcoding config, not a random ID generated fresh on each attempt), so retrying the same logical job twice is recognizably "the same job," not two different jobs.
- Visibility timeout and safe re-delivery: the queue holds a job as invisible to other workers while one worker is processing it; if that worker crashes or times out without acknowledging, the job becomes visible again and a different worker picks it up. This is what makes "the worker died mid-transcode" a recoverable event rather than a lost job.
- Atomic output publication: a worker writes its output to a temporary, uniquely-named location first, and only makes it visible under the job's final, deterministic key once the write is fully complete (an atomic rename or a conditional "put if not already present" write). This guarantees that even if two workers process the same job concurrently (a genuine possibility if a visibility timeout fires just before a slow-but-still-alive worker finishes), only one complete, correct output ever appears under the final key, never a partial or duplicated one.
- Dead-letter queue: after a bounded number of retries, a job that keeps failing moves to a separate dead-letter queue for manual inspection, rather than retrying forever and masking a genuine, unrecoverable input problem (a corrupt source file, for instance).
Worked example
A video finishes uploading and triggers a serverless function that computes a deterministic job ID (a hash of the video's storage key plus the transcoding profile), and enqueues a job under that ID. A worker picks it up, holds it invisible to other workers via the queue's visibility timeout, and begins a 40-minute transcode. At minute 25, the worker's underlying instance is reclaimed (say, it was running on spot capacity to save cost). The visibility timeout expires without an acknowledgment, the job becomes visible again, and a second worker picks it up and restarts the transcode from the beginning. When it finishes, it writes the output to a temporary path, then atomically publishes it under the deterministic final key. If the first worker had somehow still been alive and also finished around the same time, its own publish would either be a harmless overwrite of the identical content (same input, same deterministic output) or rejected by a "put if not already present" check, so the two never race into a mixed or truncated file.
Trade-offs and pitfalls
- The worker pool trades serverless's near-zero idle cost for the ability to run arbitrarily long; that's the right trade specifically because transcoding jobs are the minority of the platform's workload, not the majority, so most of the platform still gets to keep serverless's cost profile.
- A common wrong turn is making the job ID a randomly generated identifier assigned fresh on each retry attempt; that defeats idempotency entirely, since the system can no longer recognize a retried job as "the same work," and duplicate output becomes likely rather than merely possible.
- Autoscaling the worker pool on queue depth (not on CPU utilization alone) matters here: a backlog of queued but not-yet-started jobs is the leading indicator that more workers are needed, and waiting for CPU utilization to climb means the backlog has already grown before the system reacts.
Unlock Full Question Bank
Get access to all 40 Cloud Compute Options and Trade-offs interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.