A quiet service still needs a fast first response.
A Cloud Run service can scale to zero between bursts. The next request then pays for container startup and initialization — precisely when a user is waiting.
A Cloud Run service can scale to zero between bursts. The next request then pays for container startup and initialization — precisely when a user is waiting.
I built FuncWarm to schedule HTTP requests to configured targets and record their outcomes. Warmup policy stays outside business services, so I can tune intervals and observe the request path independently.
The scheduler selects a due endpoint. Real deployments should avoid synchronized bursts and unbounded overlapping work.
Selects a due target. A production schedule needs bounded concurrency, jitter and a clear policy for overlapping runs.
Schedule a target, send the request, receive its response and record the outcome.
The scheduler selects a due endpoint. Real deployments should avoid synchronized bursts and unbounded overlapping work.
The Go controller attaches a deadline and cancellation context before starting HTTP work.
An HTTP request reaches the target. Instance startup or reuse belongs to the platform, not the controller.
The controller receives the response, checks its status and measures elapsed time.
Record status and elapsed time for the target and attempt. Errors remain visible alongside successful responses.
The controller reports status and duration for each attempt. I use those observations alongside workload and infrastructure cost to choose a warmup policy.
I scheduled warmup requests to Cloud Run and recorded the outcome and response time of each attempt.
Each mark represents one successful request. The sample describes this experiment; instance retention still depends on Cloud Run.
Compare scheduled requests with continuously idle capacity. Change the workload, billing and controller costs to find the trade-off for your service.
Model scenario: the controller uses existing infrastructure, with $0 additional capacity cost. Enter its monthly overhead for your deployment.
Business traffic only; no warmup overhead
Lowest modelled spend43,200 warmup requests
Continuously retained minimum capacity
| Component | Scale to zero | FuncWarm | Minimum instances |
|---|---|---|---|
| vCPU-seconds | 0 | 4,320 | 2,592,000 |
| GiB-seconds | 0 | 2,160 | 1,296,000 |
| Requests | 0 | 43,200 | 0 |
| CPU | $0.00 | $0.10 | $6.48 |
| Memory | $0.00 | $0.0054 | $3.24 |
| Request charges | $0.00 | $0.02 | $0.00 |
| Free-tier credit | $0.00 | $0.00 | $0.00 |
| Controller + other costs | $0.00 | $0.00 | $0.00 |
USD list prices for supported Tier 1 regions, checked 2 Nov 2026. Request mode rounds execution up to 100 ms; one request uses the selected CPU/memory, without concurrent resource sharing. Minimum capacity idle time excludes active work. Instance mode uses the entered aggregate lifetime (at least active work and one minute). The monthly free-tier toggle assumes its entire billing-account allowance is unused elsewhere, applied as resource spending credits.
This is a scoped infrastructure estimate, not a complete hosting bill. Egress, logging, builds/storage, tax and committed-use discounts are excluded unless entered as other costs. Warmup requests do not reserve an instance. The measured 103/283 ms values do not change when cost assumptions change.
I designed and implemented periodic request scheduling and monitoring for the prototype.
Periodic requests trade idle capacity for scheduled work and controller overhead. I compare their incremental cost with minimum instances; Cloud Run still owns the target lifecycle.
I kept scheduling in a separate control plane. Target configuration identifies the HTTP endpoint and interval; the business service does not need its own timer or a dependency on the scheduler.
The scheduler selects a due target, the Go controller sends the HTTP request, and monitoring records the outcome and elapsed time. Context and deadline bound the operation; cancellation prevents abandoned requests from accumulating.
For multiple targets, bounded concurrency, staggered schedules and jitter keep warmup traffic from becoming a synchronized burst. A missed run should be visible in monitoring instead of silently creating an unbounded catch-up queue.
DNS failures, connection errors, HTTP errors and deadline expiry need distinct outcomes. Retry limits prevent a failing target from absorbing the controller’s capacity. Shutdown must cancel in-flight work and release resources.
For a service with sparse traffic, a short periodic request can have lower overhead than continuously retained minimum capacity. The comparison depends on request billing, target resource allocation and the controller’s operating cost.
Minimum instances is the platform setting for keeping idle capacity available. FuncWarm exercises the real HTTP path but does not reserve an instance; Cloud Run still controls retention, restarts and scaling. When predictable first-request latency is a firm requirement, that distinction matters.
My validation checklist covers a slow endpoint, a missed schedule, overlapping runs, cancellation during HTTP execution and shutdown with active requests. The assertions should check bounded in-flight work, released resources and a recorded outcome for each attempt.
Schedule lag, active requests, outcome counts and elapsed time show whether the control plane is doing useful work. Target logs and traces help distinguish a slow network path from container initialization. Cost review includes warmup traffic, controller hosting and telemetry.
In my 20-request experiment, every request succeeded. Average latency was 103 ms, maximum latency was 283 ms, and no cold attempts were observed.
A separate Go control plane centralizes warmup policy and makes request outcomes observable. I evaluate its operating cost alongside the first-response latency the service needs.