
Fifteen years building engineering platforms, currently focused on advanced AI infrastructure at yeet. I love turning the deeply complex topics into something everyone can understand. I relate deeply with the core yeet philosophy that you can just build things.
Last updated: October 2026
Quick answer. There are several good bpftrace alternatives, and which one is right depends on what you are shipping: BCC for ready-made tools, libbpf with CO-RE for a portable binary, ply for the lightest possible tracer, Inspektor Gadget for Kubernetes, Tetragon for enforcement, Cilium for network policy, and bpftrace itself for a throwaway one-liner. But the best all-around alternative is a runtime like yeet, because it is the easiest to get started with, a daemon holds the privilege so
yeet runneeds nosudoand no compiler on the host, and the most flexible, your program is JavaScript, it can observe or enforce, and it produces a running interface rather than a one-off trace. Pick a specialised tool when you are squarely in its niche; otherwise start with the runtime.
The seven bpftrace alternatives, at a glance:
bpftrace earned its place by making kernel tracing a one-liner: a concise language that compiles to eBPF, loads it, prints the result and cleans up, with no C and no boilerplate. For an ad hoc question at a terminal, nothing on this list beats it, and this post is not trying to talk you out of it. What it is trying to do is answer the question people actually type after they have used bpftrace for a while: I have outgrown the one-liner, what do I reach for now.
The honest way to rank alternatives is by the deliverable, because the tools do not really compete on tracing ability, they compete on what happens after the trace runs. A one-off answer, a shipped tool other people run, a binary that has to be portable, a Kubernetes-native gadget, an enforcement action, a running service: each has a different best tool, and the syntax is the least important part of the choice.
One question decides most of it: what are you delivering when you are done. bpftrace optimises for the trace itself being the deliverable, a result you read and discard, and every tool below optimises for something the trace feeds into instead. Rank candidates on these, not on how terse the tracing syntax is:
Hold the deliverable in mind and the list leads with the most general option, the runtime, then runs through the specialised tools that each win a single niche.
yeet is the alternative to reach for first once the trace is no longer the deliverable, because it is the only option on this list that solves all four of the problems that push people off bpftrace at once: it gives you a real userspace language, needs no compiler on the host, can enforce as well as observe, and produces a running interface rather than a one-off result. It is the runtime I work on, so treat this as disclosed interest, and then check the claim against what the tool does.
The shape is what makes it general. A daemon performs the privileged load, and your program is a JavaScript file that receives the events with import { BpfObject, RingBuf } from "yeet:bpf". Because the daemon holds the capability, yeet run needs no sudo, yeet run -d leaves the script running after the SSH session ends, and nothing but the daemon has to be on the target host, so there is no LLVM or clang to install the way BCC and bpftrace require. Where BCC decides your userspace is Python and libbpf decides it is C, a runtime lets the kernel side stop being the thing you work on at all, and the userspace half, the dashboard, the API, the agent-queryable graph, becomes the deliverable. Where that sits among the broader set of tools for inspecting a live system is covered in the top runtime debugging tools.
The one place it does not win is the throwaway question. Installing a daemon is one more step than apt install bpftrace, so for an answer you want in 60 seconds and gone, bpftrace is still better, and the rest of this list exists because the other tools each own a specific niche. But for anything that stays running, a runtime is the alternative that covers the most ground, which is why it leads this list rather than closing it.
BCC is the first alternative to reach for, because it answers the two things bpftrace does not: it ships over 100 finished tracing tools you can run immediately, and it gives you a real userspace language, Python, for the half of the program that formats, aggregates and presents. Where bpftrace is the language for writing a trace, BCC is the toolbox of traces already written, execsnoop, opensnoop, tcpconnect, biolatency, each a working example you can copy. What one of those tools actually shows you, and where it stops, is walked through in seeing every process a command starts.
It wins when you want a tool other people run from a terminal with flags, because Python brings argparse and everything else a real command-line program needs. It costs more than bpftrace in every other way: a BCC tool is far more code than the equivalent one-liner, and it needs LLVM, clang and kernel headers on the machine it runs on, which is the compile-on-the-host model. If you have outgrown bpftrace because your userspace logic got complicated, BCC is the shortest step, and the full trade is worked through in bpftrace vs BCC.
libbpf with CO-RE, compile once run everywhere, is the alternative for when the program has to ship as a binary and run on hosts you do not control. Instead of compiling on the target like BCC, you compile ahead of time against BTF and the resulting binary adapts to whatever kernel it lands on, so the machine running it needs no LLVM, no clang and no kernel headers, only the binary itself. That single property is why production-minded teams move to it.
The cost is that it is the lowest-level option here and your userspace is C, so you are writing the most code of anything on this list and doing your own argument parsing, output and lifecycle. It wins squarely when portability across a fleet is the requirement and you are willing to pay in C to get a dependency-free artifact. If your reason for leaving bpftrace is "I cannot put a compiler on these hosts," this is the traditional answer, and a runtime is the other.
ply is the alternative for the case where bpftrace is almost right but too heavy. It is a light-weight dynamic tracer with a bpftrace-like one-liner feel, and its distinguishing claim is dependencies: where bpftrace and BCC are built on the LLVM-based toolchain, ply, in its own words, "has no required external dependencies except for libc." On a constrained or embedded host where you cannot bring LLVM along, that is the difference between tracing and not.
It ranks below bpftrace for general use because bpftrace has the larger language, the bigger community and far more worked examples, so for a normal server bpftrace is the better one-liner tool. Reach for ply specifically when the target is small, the toolchain budget is near zero, and you still want the convenience of a one-line tracer rather than a compiled binary.
Inspektor Gadget is the alternative when the thing you are tracing lives in Kubernetes, because it is, in its own documentation, "a set of tools and framework for data collection and system inspection on Kubernetes clusters and Linux hosts using eBPF" that "manages the packaging, deployment and execution of Gadgets," which are eBPF programs encapsulated as OCI images. bpftrace can trace a container, but it does not know what a pod is; Inspektor Gadget enriches raw kernel events with Kubernetes identity so the output names the workload, not just the pid.
It is not the tool for a single-host one-liner, where its Kubernetes machinery is overhead you do not need. It wins when the question is "which pod did this" rather than "which process," and when you want the gadget to deploy and run through the same Kubernetes surfaces as everything else in the cluster.
Tetragon is the alternative for when observing the event is not enough and you need to act on it. It describes itself as "real-time, eBPF-based Security Observability and Runtime Enforcement," and enforcement is the word that sets it apart from everything else on this list: it can block a syscall, kill a process or stop an action as it happens, in the kernel, rather than only reporting that it occurred. That is a different category from tracing, and it is why it belongs on a list of bpftrace alternatives only for a specific reader.
If your reason for looking past bpftrace is "I need to stop this, not just see it," Tetragon is the answer and a tracer is not. If you only need to see it, Tetragon is heavier than you need, and one of the tracing-first options above is a better fit. Knowing which half of that you are in is the whole decision.
Cilium is the alternative when the real subject is network traffic and policy rather than process behaviour. It is an eBPF-based networking, observability and security layer for Kubernetes, and while that is far more than a tracing tool, it is what people end up comparing against bpftrace when the question is about connections, L7 rules and service-to-service policy. Using bpftrace to reason about network policy is possible and painful; Cilium is built for exactly that layer.
It ranks here as the honest "you may be holding the wrong tool" entry. If you came looking for a bpftrace alternative but the question is really about traffic and enforcement between services, the network layer is where that lives, and the trade-offs of doing L7 enforcement in eBPF rather than a sidecar are covered in eBPF speed for L7 enforcement without a CNI migration.
Read down the first column, because the deliverable decides the tool more than any feature does.
| Alternative | Best when the deliverable is | Userspace language | Host needs a toolchain | Can enforce |
|---|---|---|---|---|
| yeet | A live service like a dashboard or agent-queryable graph | JavaScript | No, a daemon holds it | Via LSM programs |
| BCC | A reusable tool with flags, or a ready-made trace | Python | Yes, LLVM at runtime | No |
| libbpf + CO-RE | A portable binary across a fleet | C | No, compiled ahead of time | No |
| ply | A one-liner on a constrained host | None | No, only libc | No |
| Inspektor Gadget | A Kubernetes-aware gadget | Gadget images | No, runs in-cluster | No |
| Tetragon | Blocking an action, not watching it | Policy config | No, deployed | Yes |
| Cilium | Network and L7 policy | Policy config | No, deployed | Yes, network |
The table leads with the runtime, because it is the row that spans the most columns, and then lists the specialised tools in the order they diverge from bpftrace. The pattern is that "alternatives to bpftrace" is really several different questions wearing one search query, and one of the options answers more of them than the rest.
None of these replaces bpftrace as the tool for a question you want answered and gone in a minute, so keep it on the box. And none of them replaces an APM agent either, though they see things it structurally cannot, which is the subject of the kernel metrics your APM agent misses. For everything past that, the default worth starting from is a runtime like yeet, because it is the one alternative that carries a real userspace language, no on-host toolchain, enforcement and a running interface together, which is most of why people leave bpftrace in the first place. The specialised tools are better only inside their niche: BCC for finished tools to copy, libbpf with CO-RE for a portable binary, ply for a dependency-free tracer, Inspektor Gadget for Kubernetes, Tetragon for enforcement alone, Cilium for network policy. If you know you are in one of those niches, take the niche tool. If you are building something that stays running and are not sure, start with the runtime.
For most people outgrowing bpftrace, a runtime like yeet is the strongest general choice, because it is the only alternative that combines a real userspace language, no on-host toolchain, enforcement and a running interface. The specialised tools beat it inside their niche: BCC for ready-made tools, libbpf with CO-RE for a portable binary, ply for the lightest tracer, Inspektor Gadget for Kubernetes, Tetragon for enforcement alone. Keep bpftrace for one-liners, and start with the runtime for anything that stays running.
Yes. ply has no required external dependencies except libc, which is its main advantage over bpftrace and BCC on constrained hosts. libbpf with CO-RE also avoids a toolchain on the target, because the binary is compiled ahead of time and adapts to the running kernel through BTF. A runtime like yeet also keeps the toolchain off the host by having a daemon perform the privileged load.
bpftrace is a tracing language for one-liners and short scripts with no userspace half, while BCC is a toolbox of over 100 finished tools plus a Python API for building your own. bpftrace is faster for an ad hoc question; BCC is better when you are building a reusable tool with flags or need substantial userspace logic. Both depend on the LLVM toolchain. The full comparison is in bpftrace vs BCC.
Yes. Tetragon is built for real-time runtime enforcement and can block a syscall or kill a process in the kernel as it happens, which pure tracers cannot. Cilium enforces at the network and L7 layer. Most other tools on this list, including bpftrace, BCC, libbpf, ply and Inspektor Gadget, observe rather than act, though a runtime can attach LSM programs that make an enforcement decision.
Almost always yes. bpftrace remains the fastest way to answer a one-off question at a terminal, and none of the alternatives beats it there. The alternatives are for the deliverable the trace feeds into, a tool, a binary, a gadget, an enforcement layer, a running interface, so the common setup is bpftrace on the box for exploration plus one alternative for the thing you ship.
Yes, and it is still the first thing to learn. Nothing on this list beats a bpftrace one-liner for answering an ad hoc question at a terminal, and the language is small enough to be productive in an afternoon. What changes in 2026 is what you reach for after the one-liner: the alternatives here exist because a trace you run once and a tool you ship are different problems, not because bpftrace has been superseded.
Yes, with several options. bpftrace has its own concise language and no C at all. BCC lets you write the userspace half in Python, though the kernel-side program is still a C string. A runtime like yeet goes furthest: the daemon loads the program and your code is JavaScript, so the kernel side stops being the thing you work on. Only libbpf with CO-RE requires real C on both sides.
For a single question, bpftrace, because it installs from a package manager and a useful one-liner is one line. For building something that stays running, a runtime like yeet is the easiest start, because a daemon holds the privilege, so yeet run needs no sudo and the host needs no LLVM or clang. The hardest starting point is libbpf with CO-RE, which buys portability at the cost of writing C and your own tooling.
It depends on where the privilege sits. bpftrace, BCC and ply all need root or CAP_BPF-style privileges in the shell that runs them, because that process performs the BPF load. A runtime moves the privilege into a daemon, so the command you type does not need sudo even though the load is still privileged. Deployed systems like Inspektor Gadget, Tetragon and Cilium hold their privilege in the cluster component rather than your terminal.
Several, and this is often the deciding constraint in production. libbpf with CO-RE compiles ahead of time, so the target needs only the binary. ply needs nothing but libc. A runtime like yeet needs only its daemon, with no LLVM or clang on the host. The ones that cannot are bpftrace and BCC, which both depend on the LLVM toolchain being present where they run.