Self-hosted service
laravel/zeropod avatar
laravel/zeropod

zeropod checkpoints containers to zero and wakes them on the first packet

pod that scales down to zero

968 stars41 forksGoApache-2.0

At a glance

What is it?
zeropod is a Kubernetes runtime, more specifically a containerd shim, that checkpoints a container to disk once it has been idle for a while and restores it on the next incoming TCP connection. The interesting engineering is not the checkpoint, which CRIU does, but the sequence around it: an eBPF redirector that keeps the port answering while the process is gone, and a proxy that brings the application back before the client notices.
Who is it for?
zeropod fits a team running a lot of low traffic or ephemeral services on Kubernetes where paying for idle pods is the real cost, since the checkpoint and restore path is invisible to the client and to the runtime. It does not fit a workload whose state cannot be checkpointed, since the whole design depends on CRIU being able to freeze and restore the process, and it does not fit a team on arm64 in a Linux VM on macOS, which the README flags as sometimes flaky.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • laravel/zeropod968 ★ · +2
Star history
Repository2026-10-212026-11-07
laravel/zeropod966968

2 Stars in the last 17 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Scale to zero, and what that means here

The repository describes zeropod as a pod that scales down to zero, and the README explains the mechanism. Zeropod automatically checkpoints containers to disk after a certain amount of time of the last TCP connection. While in the scaled down state it listens on the same port the application inside the container was listening on, and it restores the container on the first incoming connection. Depending on the memory size of the checkpointed program, this happens in tens to a few hundred milliseconds, which the documentation calls virtually unnoticeable to the user. The project says process memory is checkpointed and restored. That does not guarantee the state or consistency of external databases, remote services or other resources; test the complete application and its recovery behavior before relying on checkpointing. The use cases listed follow from that property. Low traffic sites, development and staging environments, a small tier on Heroku-like platforms, and mostly static sites that still need a server component.

What a containerd shim is

The README explains the layer it operates at, and it is worth following because the design constraints come from there. The shim sits between containerd and the container sandbox, and each pod has such a long-running process that calls out to runc to manage the lifecycle of all the containers of the pod. That position is exactly what zeropod needs. Because the shim is the process that owns the container lifecycle, it is the natural place to decide that the container should stop running without the runtime noticing, and the natural place to intercept traffic before it reaches the container. The project also does more than the shim, with a manager process that runs once per node as a DaemonSet, a controller component, an activator, and a CRIU image, and the top level of the repository shows the split with shim/, manager/, activator/, criu/, api/, cmd/, config/ and e2e/ directories.

Checkpoint, redirect, restore, proxy

The components that make the trick work are described one by one, and the sequence is the interesting part. Checkpointing is done using CRIU. After checkpointing, a userspace TCP proxy, the activator, is created on a random port and an eBPF program is loaded to redirect packets destined for the checkpointed container to the activator. The activator then accepts the connection, restores the process, signals to disable the eBPF redirect and proxies the initial requests to the restored application. The activation diagram fills in the timing, with the client connecting, the redirector sending the connection to the activator, the activator restoring the container and then repeatedly connecting to the restored process until it accepts, after which the connection is redirected back to the client's original local port. The loop is the honest part of the design, because the restored process needs a moment before it can accept a connection. After the first requests, all subsequent connections go directly to the application without any proxying and performance impact.

The same eBPF program decides when to sleep

The redirector eBPF program is also used to track the last TCP activity targeting the running application, and that is used to delay checkpointing when there is recent activity. The purpose is stated plainly, to avoid too much flapping on a service that is frequently used. Without it, a service with a bursty pattern would checkpoint and restore repeatedly, and the restore cost, even at a few hundred milliseconds, would dominate. The eBPF approach also means the decision is made where the packets are, not by polling. The rest of the trick is that the container appears to be running to the container runtime even though the process is technically not, and the README says that this is required to prevent the runtime from trying to restart the container. When you run kubectl exec against a scaled down container, it is restored and the exec works as with any normal Kubernetes container.

Metrics, resource scaling and migration

Metrics are recorded continuously within each shim, and the zeropod-manager process, which runs once per node as a DaemonSet, collects and merges the metrics from the different shim processes. The shim exposes a unix socket for the manager to connect, and the manager exposes the merged metrics on an HTTP endpoint. That arrangement keeps the per-pod process small and pushes the aggregation to a node level daemon, which is the arrangement a Prometheus scraper expects. The project also adjusts resource requests in the scaled down state in place if the cluster supports it, and scaled down pods can be migrated between nodes without needing to start up, which is what prevents a huge resource usage spike when draining a node. There is a more experimental live migration feature that stretches the scaling use cases further.

Compatibility, and where to look when it fails

The compatibility position is optimistic with one caveat attached. Most programs should just work with zeropod out of the box, and the examples directory contains a variety of software that has been tested successfully. When something fails, the containerd logs are the place to look, because they output the CRIU log on a checkpoint or restore failure, which is exactly the information you need to know whether the failure was in the checkpoint or in the restore. The caveat is specific. Some arm64 workloads running in a Linux VM on top of macOS have proven somewhat flaky sometimes. That is a narrow statement, but it is also the environment many developers work in, so it is worth knowing before you build a development workflow on top of the project. The documentation lives in the docs/ directory and the example configurations in config/examples.

The build, the images and the dependency set

The Makefile shows that this is a multi image project, with separate images for the installer, the manager, the test harness, the eBPF program and CRIU, all published under the laravelphp namespace with a dev tag, and the CRIU version pinned in the file at v4.2.1. There is a build-kind target for fast local development that copies the shim binary into a kind worker container, with the note that running pods have to be recreated to pick up the new shim, and the platforms built are linux arm64 and linux amd64. The dependency list is the most informative part of the project metadata. It includes the CRIU bindings, replaced with a fork by the ctrox project, the cilium eBPF library, the containerd API and runtime libraries, the containerd CRI client and the Kubernetes client libraries, controller-runtime and kustomize, and the Prometheus client. The Go version is 1.26.3. The releases are v0.13.0 on 2026-08-23, v0.12.1 on 2026-06-29 and v0.12.0 on 2026-05-21, the last push was on 2026-10-15, and the licence is Apache-2.0.

Editorial conclusion

zeropod fits a team running a lot of low traffic or ephemeral services on Kubernetes where paying for idle pods is the real cost, since the checkpoint and restore path is invisible to the client and to the runtime. It does not fit a workload whose state cannot be checkpointed, since the whole design depends on CRIU being able to freeze and restore the process, and it does not fit a team on arm64 in a Linux VM on macOS, which the README flags as sometimes flaky. Before you try it, read the compatibility notes and the example configurations, and expect to look at the containerd logs when a restore fails, because that is where the CRIU output goes.

Frequently asked questions

What is zeropod?

It is a Kubernetes runtime, more specifically a containerd shim, that automatically checkpoints containers to disk after a period without TCP connections, listens on the same port while the container is scaled down, and restores the container on the first incoming connection, usually within tens to a few hundred milliseconds.

How does zeropod restore a container without the client noticing?

After checkpointing, a userspace TCP proxy called the activator is created on a random port and an eBPF program redirects packets destined for the container to it. The activator accepts the connection, restores the process, disables the redirect and proxies the initial requests, so later connections go straight to the application with no proxying overhead.

Does the container runtime know the container is stopped?

No, and that is deliberate. To the container runtime the container appears to be running even though the process is technically not, which is required to prevent the runtime from trying to restart the container. Running kubectl exec against a scaled down container restores it and the exec then works as with any normal container.

What happens when a checkpoint or restore fails?

The containerd logs are where to look, because they output the CRIU log on a checkpoint or restore failure. The compatibility notes also flag that some arm64 workloads running in a Linux VM on top of macOS have proven somewhat flaky.

Is zeropod still updated?

The repository is not archived and the last push was on 2026-10-15, with v0.13.0 released on 2026-08-23, v0.12.1 on 2026-06-29 and v0.12.0 on 2026-05-21. The licence is Apache-2.0 and the module path is github.com/laravel/zeropod, built with Go 1.26.3.

Official sources

  1. Issues
  2. laravel/zeropod on GitHub
  3. License: Apache-2.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/laravel-zeropod.svg)](https://hysenlabs.com/projects/laravel-zeropod)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/laravel-zeropod.svg)](https://hysenlabs.com/projects/laravel-zeropod)

Was this useful?