Christian Lehnert — Linux, Hacking & Faith

The Sidecar Pattern - Bolting Capabilities Onto a Pod Without Touching the App

Christian Lehnert2026-08-11~6 min read

The Sidecar Pattern

More Than One Container in a Pod

Most people meet the pod as "the thing that holds my container." Then
they learn a pod can hold several, and the obvious question is why you
would ever want that. The sidecar pattern is the best answer.

A sidecar is a second container in the same pod as your application,
running beside it to add a capability the application does not provide
itself. The name is the motorcycle sidecar: bolted to the main vehicle,
along for the ride, carrying something the bike alone could not. The
main container does its job. The sidecar handles a concern next to it,
and the application never has to know.

Why a Pod, Not Just Another Deployment

The reason this works, and the reason a sidecar is different from just
running another service, is what containers in the same pod share.

They share a network namespace. The sidecar and the app see the same
localhost. The sidecar can reach the app on 127.0.0.1 and the app can
reach the sidecar the same way, with no service, no DNS, no network hop
across the cluster. To each other they are on the same machine.

They share storage when you want them to. A volume mounted into both
containers is a place they can hand files back and forth. The app
writes, the sidecar reads, or the other way around, through the
filesystem, with no protocol between them.

And they share a lifecycle. They are scheduled together onto the same
node, started together, and stopped together. The sidecar is always
exactly where the app is, one per app instance, scaling with it
automatically. You never have to place them together, because the pod
guarantees it.

That trio, same network, same storage, same lifecycle, is what makes
the sidecar a genuine extension of the application rather than a
separate thing that happens to be nearby.

What People Actually Use It For

The pattern shows up everywhere once you recognize it.

Logging. The app writes logs to a file or stdout, and a sidecar picks
them up, parses them, and ships them to your log system. The app knows
nothing about where logs go. Swap the log backend and you change the
sidecar, not the application.

Proxying, which is the whole basis of a service mesh. A sidecar proxy
sits in front of the app's network traffic and handles mutual TLS,
retries, timeouts, and traffic routing. The app makes a plain call to
localhost and the sidecar turns it into a secured, observable,
policy-controlled request across the mesh. The application code stays
oblivious to all of it.

Secret and config watching, which is the case on the slide that
prompted this. A sidecar watches an external source, a secret store or
a config service, and when something changes it updates a shared file
the app reads, or signals the app to reload. The app just reads its
config file. The sidecar keeps that file current. The watcher
capability lives entirely beside the app, asynchronously, never in its
request path.

Data preparation. A sidecar pulls data, clones a git repo, syncs
content, and drops it on a shared volume the app serves from. The app
serves files; the sidecar keeps them fresh.

The common thread in all of these: a concern that is not the
application's core job, that you do not want to build into every
application, attached from outside where it can be maintained on its
own.

Why This Is Worth Doing

The value is separation. The application does one thing, and the
cross-cutting concerns, logging, security, config refresh,
observability, live in their own containers you build, version, and
update independently.

You write the log shipper once and attach it to forty different
applications, in whatever languages they happen to be, and none of them
contains a line of log-shipping code. You upgrade the mesh proxy across
the whole fleet by changing the sidecar image, not by touching or
redeploying a single application. A concern that would otherwise be
copy-pasted into every service, in every language, becomes one
container maintained in one place. That is the payoff, and it is a big
one at scale.

It is also how you add capabilities to software you cannot change. A
third-party image, a legacy app nobody wants to rebuild, gets modern
logging and mesh networking bolted on beside it without altering the
thing itself.

When It Turns Into Bloat

The sidecar is not free, and the failure mode is stacking too many of
them.

Every sidecar is another container consuming CPU and memory in the pod,
next to every replica. One lightweight sidecar is cheap. Five heavy ones
means each pod now runs six containers, and the overhead multiplies
across every replica of every deployment. The proxy alone, on a large
mesh, can consume a real share of a cluster's resources, all of it spent
on containers that are not your application.

Startup ordering used to be a genuine trap: a sidecar that had to be
ready before the app, or shut down after it, was awkward to express, and
apps would start before their proxy was up and fail their first
requests. Native sidecar support in recent Kubernetes fixed the worst of
this by giving sidecars a proper lifecycle that starts them first and
stops them last, but the lesson stands. Every sidecar is another moving
part in the pod's startup and shutdown, and more parts is more that can
go wrong.

The discipline is the same as everywhere else. A sidecar earns its place
when it removes a concern from the application that genuinely does not
belong there. It becomes bloat when it is reached for reflexively, and
the pod slowly grows a committee of containers nobody can fully account
for.

The Point

A pod holds more than one container so that you can attach capabilities
to an application without changing it. The sidecar rides beside the app,
sharing its network, its storage, and its lifecycle, handling the
cross-cutting concern, logging, proxying, config watching, secret
rotation, that you do not want built into the app itself. Write it once,
attach it everywhere, maintain it on its own.

Use it to keep the application focused on its job and the plumbing out
of its code. Watch the resource cost when they stack up, and add each
one on purpose, because a pod full of sidecars nobody remembers adding is
its own kind of mess.

Tagged:
#kubernetes #sidecar #design-patterns
← Back to posts