Why eBPF stops at the Windows node boundary — and what we built instead
Day two of Nyx being public. Yesterday was the announcement; today is the technical story behind the one claim in it that raises eyebrows: kernel-level network security with behavioural parity across Linux and Windows Server nodes. This post explains why that's rare, why it's hard, and how we approached it.

The blind spot nobody talks about
If you run Kubernetes in a large enterprise — a bank, an insurer, a hospital network, a government department — there's a decent chance your cluster isn't all Linux. Somewhere in there is a Windows node pool running the workloads that never got rewritten: the .NET Framework services, the IIS-hosted applications, the Sitecore CMS the marketing team depends on. Kubernetes has supported Windows worker nodes for years precisely because these workloads exist and matter.
Now ask a simple question: what does your network security tooling see on those nodes?
For most modern cloud-native security stacks, the honest answer is: nothing. The flow logs stop. The policy enforcement stops. The observability map has a hole in it shaped exactly like your Windows node pool. Your zero-trust program — the one with the executive sponsorship and the compliance deadline — quietly excludes the workloads running on Windows, and everyone hopes the auditor doesn't ask.
This isn't because vendors are lazy. It's because of a genuine technical boundary.
Why eBPF doesn't cross the line
The last decade's biggest leap in Linux networking and observability is eBPF: the ability to load small, verified programs into the Linux kernel and attach them to hooks — traffic control, sockets, tracepoints — so you can observe and act on every packet and connection in the kernel itself, with no sidecars, no proxies, and near-zero overhead. It's a genuinely brilliant piece of engineering, and it's the foundation of the best modern tooling in this space.
But eBPF is not a portable standard. It is a subsystem of the Linux kernel — the verifier, the JIT, the hook points, the helper functions are all Linux internals. Windows has no equivalent runtime in its production server kernels. (There's an open-source eBPF-for-Windows effort, and it's interesting work — but it's a different runtime with a different maturity curve, and it isn't the basis on which you make enforcement guarantees to a regulated enterprise today.)
The consequence is structural, not incidental: any security architecture built on eBPF inherits eBPF's boundary. The tooling doesn't degrade gracefully on Windows nodes — it simply isn't there. The dataplane that gives you kernel-level truth on Linux gives you nothing at all on the node next to it.
For all-Linux shops, this doesn't matter. For the mixed-estate enterprises that most need zero trust — which are, not coincidentally, the most regulated ones — it's the gap in the middle of the security posture.
What Windows actually offers
Here's the part that surprised us when we started: Windows does have a kernel-level answer. It's just a completely different one.
The Windows Filtering Platform (WFP) is the packet-processing framework built into the Windows kernel — it's the machinery underneath Windows Firewall and most serious Windows network security products. It allows a signed kernel driver to register callouts: functions the kernel invokes at defined layers of the network stack, with the authority to inspect, permit, or block traffic as it flows. Done properly, a WFP callout driver gives you on Windows what eBPF gives you on Linux: visibility and enforcement in the kernel, at the point of truth, without proxies or agents-in-the-datapath.
"Done properly" is carrying a lot of weight in that sentence. A WFP callout is a kernel driver, and Windows kernel drivers for Server platforms must pass Microsoft's Hardware Lab Kit (HLK) certification — a formal test suite run against the exact target OS build, submitted to Microsoft, and signed by Microsoft — before a production Server kernel will load them. There is no shortcut around this for Server-class machines: the kernel itself enforces it. This is a meaningful part of why so few cloud-native vendors go here. It's slow, exacting work in an unfamiliar toolchain, and it has to be redone for each OS version you support. (That certification journey deserves its own post — coming next week.)
Parity is the actual hard problem
Building two dataplanes is work. Making them behave the same is the hard problem — and it's the one that matters, because a policy model that means different things on different nodes is worse than useless in a compliance context. "Deny" has to mean deny, identically, whether the pod landed on Linux or Windows. An audit event has to carry the same semantics. A dry-run has to be equally side-effect-free.
The two kernels give you very different raw materials. On Linux, we attach eBPF programs at traffic control hooks and see traffic per-packet at the interface. On Windows, WFP callouts operate at connection- and flow-oriented layers of the stack. Different granularities, different lifecycle events, different metadata. The engineering that matters isn't either driver in isolation — it's the abstraction above them: one policy schema, one priority model, one set of enforcement modes (dry-run, audit, enforce), compiled down to each kernel's native enforcement machinery, with the differences absorbed below the API so the person writing the policy never has to think about them.
That's the bar we set for Nyx: not "Windows support" as a checkbox, but the same NyxNetworkPolicy, the same verdict semantics, the same observability, on every node in the cluster. One security model. Two kernels underneath it.
What this looks like in practice
On a mixed AKS cluster, the experience is deliberately boring: you install one Helm chart for your Linux nodes and one for your Windows pool, and the traffic map simply shows everything — the .NET service on the Windows node talking to the Linux-hosted API, the egress from an IIS pod resolving to a hostname, all of it recorded in the kernel the instant it happens. A policy that denies cross-namespace traffic denies it on both sides. A dry-run shows you what would have been blocked on both sides, before you enforce anything anywhere.
The Windows enforcement runs through our WFP callout driver, HLK-certified for Windows Server 2022 and signed by Microsoft — which is not marketing language, it's a load-time requirement the Windows kernel enforces. If a vendor tells you they do kernel-level enforcement on Windows Server, the certification is the receipt to ask for.
The honest scope
Precision matters more than reach in this space, so: today, the certified Windows enforcement targets Windows Server 2022 nodes; Linux enforcement is eBPF-based on AMD64 nodes across any conformant Kubernetes — we've run it on AKS, EKS, and GKE. Where the two platforms' capabilities genuinely differ, we document the difference rather than paper over it. A security tool that's vague about its own boundaries has no business asking you to trust its enforcement of yours.
The point
None of this is an argument against eBPF — we build on it, and it's the right foundation on Linux. The argument is narrower and, we think, more useful: the boundary of your security tooling should be decided by your security requirements, not by your dataplane's operating-system preferences. Mixed estates are a reality in exactly the organisations where zero trust matters most. The kernel is the right place to enforce on both sides of that estate. It just takes two very different roads to get there.
If you're running Windows nodes and you've been told "that's not supported" — that sentence is the reason Nyx exists. There's a free tier and the install takes about a minute: tracenyx.ai.
Next up: the story of getting a kernel driver through Microsoft's HLK certification as a bootstrapped startup — the lab, the failures, and the tool we ended up building and open-sourcing along the way.



