What Makes API Design an Art, Not a Science
Christoph Stiller's C++Online 2026 talk breaks down why good API design is a discipline in itself—and what separates craft from afterthought.
Written by AI. Dev Kapoor

Photo: AI. Dexter Bloomfield
There's a quiet injustice embedded in how most engineering teams operate. Junior developers get code-reviewed constantly—their variable names scrutinized, their loops questioned, their formatting debated. That feedback loop, relentless as it is, is also how they grow. But when it comes to API design and architecture? Those decisions tend to float upward, handled by whoever has the most tenure and the most implicit trust. The people who need the practice most never get the reps.
That's the observation Christoph Stiller opens with in his talk at C++Online 2026, and it's a better framing than most design talks bother with. Stiller—a software engineer who has built core libraries, codecs, compression tools, and anti-tampering systems across his career—isn't pitching a framework or selling a methodology. He's doing something more useful: trying to give less experienced engineers a map of terrain they're usually dropped into without one.
"A good API is not just a byproduct of functionality or some afterthought," Stiller says, "but actively designed to help the user."
That distinction—designed versus incidentally produced—runs through everything that follows.
The problem with building bottom-up
Most developers, when tasked with building a new system, start at the bottom. Neurons before layers, layers before training engine, training engine before the neural network interface the user actually touches. It's the natural way to build: you implement what you understand, then stack abstractions on top until the thing works.
The problem, as Stiller explains it, is that this makes the API a consequence of implementation decisions rather than a design decision in its own right. By the time you've built four layers of internals, your public interface is shaped by constraints that your users never needed to care about. You've built the house and then tried to figure out where the front door should go.
His preferred alternative is what he calls "bottom top down"—a hybrid that acknowledges the legitimate tension here. You start by building the lowest-level components first, so you actually know what the hard constraints are. Then, crucially, you write fake user code before touching the intermediate layers. You prototype the ideal interface before implementing it. Only once you know what the top and bottom look like do you build the middle.
This is easier said than done—knowing what your lowest level even is can itself be unclear—so Stiller offers a pragmatic fallback: pick one end-to-end interaction, imagine the full call chain from user code to implementation, and trace it through. Then do the next one. Patterns emerge. Layers clarify. You're designing from evidence, not guessing.
The pseudo-code step is where a lot of people check out, because it feels like work that doesn't ship. But the argument for it is hard to dismiss: your API doesn't exist yet, which means pseudo-code can give you any interface you want. No legacy, no existing class hierarchies, no "well, it's easier if we just expose this internal state." Pure design.
What your language constructs are already saying
One of the more interesting threads in the talk is about the silent communication happening through language constructs themselves. Stiller makes the case that struct and class in C++ are functionally nearly identical—but carry completely different social meanings among developers. A struct implies POD-like simplicity, something you'd pass around and copy without ceremony. A class implies lifetime management, encapsulation, probably inheritance somewhere. Modifying a member of a struct directly is normal. Doing the same to a class raises eyebrows.
Stiller extends this to the full vocabulary of C++ type choices—const references, raw pointers, rvalue references, static functions, free-floating functions. Each one carries baggage, expectations, a personality. An API that uses these consistently and intentionally is one where users can carry their existing knowledge directly into your codebase. An API that mixes them arbitrarily or ignores what they conventionally signal creates a cognitive load that looks like confusion but is actually unnecessary friction.
This is where the talk's subtitle—"art, not science"—starts earning its keep. There's no compiler error for using a class where a struct would communicate more clearly. The constraint is entirely social. It lives in the shared mental model of your target audience, which is exactly why Stiller emphasizes knowing who that audience is before making these calls. "The better you can define it," he notes, "the easier it will be to make the right decisions for them."
The "target audience" framing isn't just marketing-speak transplanted into engineering. It's a genuine design constraint. An API for people deeply familiar with the STL can lean on std::span and std::expected without explanation—those idioms carry meaning to that audience. An API for newer developers might need different scaffolding entirely.
The complexity slope and the 95% trap
Here's a tension that doesn't get discussed enough: the temptation to optimize only for the simple case. Stiller has a name for the right shape of an API's difficulty curve—the "complexity slope"—and it's a useful concept precisely because it resists both extremes.
The failure mode he's warning against isn't just bad API design in the abstract. It's the very specific error of making the common case trivial at the expense of making hard cases impossible. A basic audio playback call should be one line. It genuinely should. But a highly configurable multi-stage conversion pipeline shouldn't be—and pretending otherwise either forces the complex case into hacks or quietly excludes it.
"Simple interactions should be trivial," Stiller says, "but complex interactions that are valid should still be possible."
The trap for the other direction is equally real: don't make trivial interactions require a diploma. The complexity slope's gradient should be reasonable throughout—not flat at the bottom and then a cliff wall, not a gentle incline that somehow never reaches the peak.
What's appealing about this framing is that it reframes API quality as a property of the entire system—the API code plus all the code that uses it. Stiller's point that a messier implementation behind a clean public interface is often worth it is worth sitting with. It runs counter to the instinct to keep your own code clean at all costs. But your implementation is yours to change. The interface is everyone's problem the moment it ships.
The slow decay of good APIs
Stiller closes with a point that's less about initial design and more about maintenance: even well-designed APIs die over time. Parameters accumulate. Edge cases get bolted on. Someone needed one configuration option, then another, then a third, and now a function signature that was once clean looks like it was designed by committee.
This is entropy, and it's almost impossible to prevent entirely—but it can be slowed by treating API changes with the same scrutiny as API design. Every addition carries long-term consequences. Sometimes the right answer to "we need a new option here" is to introduce a new abstraction layer, or to drop down to a lower one, rather than to add the parameter and move on.
The harder discipline is the review culture around interface changes. Code review catches bad implementations regularly. Interface changes that will calcify over years? Those often slip through because the damage is slow-moving and hard to see in a diff.
Stiller's framework for evaluating existing APIs is worth keeping: look at the architecture's mental model, look at the interface code itself, then look at how people are actually using it. The client code is especially revealing—whenever users are circumventing abstraction boundaries or doing unexpected gymnastics to accomplish something reasonable, that's the API telling you something it couldn't say directly.
Most of what Stiller covers here isn't novel in isolation—single responsibility, consistency, knowing your audience—but the synthesis is what makes the talk useful. API design advice is usually delivered as a list of properties to aim for. What Stiller offers instead is a design process: start with pseudo-code, build the right direction, stay consistent, resist entropy, watch how your users actually behave.
The deeper question his talk raises, and doesn't quite resolve, is structural: if junior engineers are kept away from API decisions because their early attempts aren't great, and they're kept away from API decisions, how does that improve? The skill compounds only when you practice it, and you only practice it when someone trusts you with it. That cycle doesn't break by watching a conference talk—but it might start to, if the people holding the decisions watch one too.
By Dev Kapoor, Open Source & Developer Communities Correspondent, Buzzrag
We Watch Tech YouTube So You Don't Have To
Get the week's best tech insights, summarized and delivered to your inbox. No fluff, no spam.
More Like This
How Cloudflare Uses Lava Lamps to Encrypt the Internet
Cloudflare's San Francisco office has a wall of 100 lava lamps generating entropy for SSL/TLS encryption. Here's why computers can't be truly random.
Bridging the Gap: C++ Workshop Tackles Industry Reality
Amir Kirsh's workshop addresses the persistent divide between academic C++ and production code—and questions whether one-day training can solve it.
The macOS TCP Bug That Detonates at 49 Days
A uint32 cast in macOS's TCP clock code means any Mac left running past 49 days hits a networking wall. Here's exactly how it breaks—and why it matters.
When Hackers Build Cameras That Freeze Reality
A maker built a custom camera rig that makes spinning saw blades appear motionless. The technical choices reveal what consumer cameras hide from us.
Why Your C++ Code Is Secretly Unmaintainable
Klaus Iglberger's workshop preview reveals how dependencies and coupling quietly transform simple C++ codebases into nightmares nobody wants to touch.
Why Senior Engineers Struggle Most With AI Agents
Philipp Schmid breaks down 5 mental model shifts that trip up experienced engineers when building AI agents — and why expertise can be the actual problem.
GSD Framework Tackles AI Coding's Real Problem: Choice
GSD, BMAD, and Superpowers take radically different approaches to AI coding. The AI LABS team breaks down when each framework actually works.
AWS Identity Center's Multi-Region Replication Feature
AWS just launched multi-region replication for Identity Center. Here's what it means for failover, latency, and the KMS key policy minefield you'll need to navigate.
RAG·vector embedding
2026-06-16This article is indexed as a 1536-dimensional vector for semantic retrieval. Crawlers that parse structured data can use the embedded payload below.