automemlimit
Automatically sets Go's GOMEMLIMIT from the Linux cgroup memory limit so the garbage collector stays aware of container memory constraints.
Repository Health
Technical Analysis
automemlimit reads the memory limit assigned to a process by Linux cgroups (v1 or v2) and uses it to configure Go’s GOMEMLIMIT, the soft memory cap the garbage collector uses to avoid over-committing heap growth. Without it, a Go binary running in a container or Kubernetes pod has no idea it’s memory-constrained and can keep growing its heap until the kernel OOM-kills it — even though runtime/debug.SetMemoryLimit has existed since Go 1.19, nothing sets it automatically from the environment.
The simplest usage is a single blank import (import _ "github.com/KimMachineGun/automemlimit") which sets GOMEMLIMIT to 90% of the detected cgroup limit at process start. The memlimit subpackage exposes the same logic as a composable API — configurable ratio, minimum bound, custom or fallback providers, periodic refresh for containers whose limits change at runtime, and structured logging — for callers who need more control than the side-effect import gives them.
What You Get
- A zero-config blank import that sets GOMEMLIMIT to 90% of the cgroup memory limit as soon as the process starts
- A
memlimit.SetAPI with functional options for ratio, minimum bound, custom providers, and periodic refresh - Correct cgroup v1 and v2 detection, including nested hierarchy walking and conflicting-mount resolution via
/proc/self/mountinfoand/proc/self/cgroup - A
FromSystemfallback provider (viagithub.com/pbnjay/memory) for processes running outside cgroups entirely - Structured
log/sloglogging of every limit change, with a safe no-op default when logging isn’t configured
Common Use Cases
- Preventing Go services in Kubernetes pods from being OOM-killed by making the GC aware of the pod’s memory request/limit
- Running Go binaries in Docker containers with
-m/--memorylimits without hand-tuning GOMEMLIMIT per deployment - Reacting to memory limits that change at runtime (e.g. vertical pod autoscaling) via the periodic refresh option
- Falling back to total system memory as a soft limit for processes that aren’t containerized at all
Under The Hood
Architecture
The module splits into a root automemlimit package holding only a side-effect init() that calls memlimit.Set with a default slog logger, and a memlimit subpackage carrying all the logic: memlimit.go defines the functional-options Set entrypoint and config struct, provider.go defines the Provider type (func() (uint64, error)) plus composable wrappers ApplyRatio, ApplyFallback, and Limit, cgroups.go/cgroups_linux.go/cgroups_unsupported.go handle cgroup v1/v2 detection behind Linux/non-Linux build tags, and system.go supplies a total-system-memory fallback. Set composes a provider chain (ratio-adjusted, then bounded by a configured minimum), calls runtime/debug.SetMemoryLimit, and optionally starts a refresh goroutine on a ticker. Because every wrapper depends on the same Provider function signature, changing that one abstraction would ripple through the entire package.
Tech Stack
Pure Go, targeting go 1.21+, with a single external dependency (github.com/pbnjay/memory) used only for the system-memory fallback provider. Everything else is stdlib: runtime/debug.SetMemoryLimit, log/slog, and direct parsing of /proc/self/mountinfo and /proc/self/cgroup. There’s no build tooling beyond go build/go test; the examples/ directory ships three standalone example modules (dynamic, logger, system) each with their own go.mod. CI runs the test suite inside real golang:1.21 Docker containers launched with -m=<limit>, asserting the actual resulting GOMEMLIMIT against expected values on both Ubuntu 22.04 and 24.04 runners.
Code Quality
Test coverage is extensive and unusually rigorous for the domain: cgroups_test.go (27KB) and its fixtures exercise v1/v2 mount and hierarchy parsing edge cases, memlimit_test.go/memlimit_linux_test.go cover the Set option surface, provider_test.go covers ratio/fallback edge cases (NaN, zero, truncation), and build-tag-gated *_unsupported_test.go files assert graceful behavior on non-Linux platforms. Errors are sentinel-typed (ErrNoLimit, ErrNoCgroup, ErrCgroupsNotSupported), checked with errors.Is, and wrapped with %w throughout rather than swallowed. There’s no dedicated lint config in the repo, but CI additionally runs real container-based integration tests rather than relying solely on mocks.
API Design
The library offers two entry points at different levels of ceremony: a zero-boilerplate blank import (import _ "github.com/KimMachineGun/automemlimit") for the common case, and memlimit.Set(opts ...Option) with idiomatic functional options (WithRatio, WithMin, WithProvider, WithLogger, WithRefreshInterval) for callers who need to customize the ratio, supply a fallback provider chain, or refresh on an interval. The Provider abstraction (func() (uint64, error)) is small and composable — ApplyRatio, ApplyFallback, and Limit all take and return a Provider, so callers can build custom sources without touching the library’s internals. Naming is consistent and documentation is thorough — every exported option and error documents its default and behavior inline via godoc comments — and the README leads with the simplest possible usage before showing the configurable API, minimizing the boilerplate needed to get started.
Used by 4 apps in this directory
Caddy
Devops · Security
The only web server that obtains and renews TLS certificates automatically, with HTTP/1-2-3 support and zero dependency on external runtimes.
opencloud
File Storage
Open source file management and collaboration platform that keeps your data under your control, no database required.
SpiceDB
Security · Authentication · Databases
An open source, Google Zanzibar-inspired authorization database that models permissions as relationships and evaluates fine-grained access checks at massive scale with single-digit millisecond latency.
Weaviate
Databases · Search
Open-source vector database combining semantic search, hybrid queries, RAG, and image search in a single cloud-native system built for production scale.