ZopDay Puts Idle VM Services to Sleep, Cuts Waste
A service deployed on a VM used to run continuously, holding its full memory allocation whether one visitor showed up that hour or none did. That’s the default assumption most deploy paths make: a running service stays running until someone explicitly stops it. On a shared pool VM, where multiple orgs’ services compete for the same physical memory, that assumption gets expensive fast: idle VMs running non-stop are one of the most common ways idle compute quietly becomes most of a monthly bill. Ten services nobody is actively using still cost exactly as much as ten services under real load.
ZopDay’s VM services can now sleep when idle and wake automatically on the next request. Turn it on once per space in Infrastructure settings, pick an idle window anywhere from 1 minute to 24 hours, and a service that’s gone quiet stops and gives its memory back. The next visitor triggers a wake, not a 404.
One Switch, One Idle Window, Zero Ongoing Maintenance
The feature is opt-in per space, not per service. Turn it on once in Infrastructure settings and every HTTP-fronted service in that space becomes eligible for sleep. The idle window is configurable from 1 minute up to 24 hours, with a default of 30 minutes. Set it short for services where a slow first-load after waking is fine, or long for anything where you’d rather trade some idle memory for a service that’s always warm.
Nothing about how a developer deploys or configures a service changes. The sleep behavior sits entirely in front of the service, which is what makes it something a platform team can turn on for a whole space without asking every team to change how they ship.
The Mechanism: A Proxy That Holds the Docker Socket
The feature ships as a new VM component: a Sablier-enabled build of Caddy paired with a sidecar, zop-sablier, that holds the Docker socket. It’s the same scale-to-zero pattern KEDA applies to containerized workloads, moved to the VM layer. Caddy sits in front of every HTTP-fronted service on the VM. When a service goes quiet past its idle window, the sidecar stops its container and frees the memory. The next request to that service doesn’t 404. It hits a wake page while the sidecar starts the container back up, then Caddy forwards the request through once the service is ready.
That design keeps the sleep behavior entirely at the proxy layer. The service itself doesn’t need to know it can be stopped and started; Caddy and the sidecar handle the whole lifecycle in front of it. This works when a service is reached over HTTP, so a request can trigger the wake. It breaks when a service isn’t reached over HTTP at all, since there’s no request for the proxy to intercept and answer with a wake page.
Shipped Dark: No Existing VM Is Affected Until You Opt In
This component isn’t part of the default VM baseline. A VM that existed before this release keeps running exactly as it did until an operator explicitly installs the sleep component on that space. That distinction matters for a feature that changes what “the service is unreachable” means: a service that used to always respond now sometimes shows a wake page first. Shipping it dark means that behavior change only happens somewhere a team actively chose it, not everywhere the code got deployed.
The Cross-Org Bug an Opt-In Feature Almost Shipped With
A shared pool VM runs services from more than one org side by side. The check that decides whether to render the sleep route looked at whether the installing org had a component-install record, which works fine for the first org that installs the feature on a given VM. It breaks for the second org sharing that same physical VM: that org has no install record of its own, the check reads as “not installed here,” and its service deploys with no sleep support at all, silently, with no error to signal that anything was skipped.
The fix replaces the org-scoped check with a target-scoped one: it asks whether the sleep component is installed on this VM, not whether this org is the one who installed it. That’s the correct question on shared infrastructure, where the resource being checked (the VM) is shared but the check was written as if it belonged to one tenant.
| Check | What it answers | What breaks on a shared VM |
|---|---|---|
| Org-scoped (before) | Did this org install the sleep component? | A second org on the same VM reads as “not installed,” deploys without sleep support |
| Target-scoped (after) | Is the sleep component installed on this VM? | Correctly recognizes the install regardless of which org performed it |
The org-scoped check wasn’t wrong everywhere. It’s kept, deliberately, for a separate upgrade-gate path where the question really is about the specific org, not the shared VM. Only the install-detection path needed to change. The rollback plan reflects how narrow that fix is: reverting the cross-org fix alone puts the bug back on a live shared VM, while reverting the base sleep feature entirely, with or without that fix, is safe either way.
