Why Good APIs Are Like Ogres
23 Oct 2025Good APIs are like ogres: they have layers.
However, where an ogre hides its gentle core behind a rough exterior, an API should do the reverse: presenting a friendly surface while hiding its complexity within.
The outermost layer should be the most approachable, offering convenient shortcuts for common tasks. The innermost layer should be the most powerful, exposing all capabilities at the cost of verbosity or complexity.
![]()
Layers in Spring MVC
An example of layering can be found in Spring MVC. Each layer is public and designed for user consumption, but they differ in abstraction, convenience, and scope.
- Annotation-based layer:
@Controller,@RequestMapping, and friends.
The most user-friendly entry point: concise and expressive, though not suited for every edge case. - Extension points: such as
HandlerMethodArgumentResolverandHandlerMethodReturnValueHandler. These allow customization and integration while keeping the annotation model intact. - Servlet API: the foundation. It defines the raw HTTP abstraction for Java web applications. If something is not possible here, it cannot be done in higher layers either.
Each layer offers a different “view” of the web programming model at its own abstraction level.
You can write a Servlet that accomplishes the same as a @Controller, but it will require much more code.
Layers in WebMvc.fn
The WebMvc.fn functional API follows a similar pattern:
- Builders:
RouterFunctions.routeand related helpers.
These provide a fluent and readable way to define routes and handlers. - Component model:
HandlerFunctionandRouterFunction.
A composable core that allows for extension and reuse. - Servlet API: again, the foundation underneath.
Simple, Not Simplistic
The most important design rule is that higher layers must be able to reach the lower ones. Otherwise, the API becomes simplistic rather than simple: pleasant for trivial cases, but too limited for anything beyond them.
Spring provides many examples of this principle:
- In Spring MVC, a controller method can declare a
HttpServletRequestorHttpServletResponseparameter, giving access to the Servlet API when needed. - In WebMvc.fn, you can use a
WriteFunctionto directly interact with the request and response.
This ability to “peel back the layers” ensures that convenience never comes at the cost of capability.
The Broader Lesson
Every mature API should have layers. The top layers express the most common workflows in the most user-friendly terms. The lower layers expose the raw capabilities for edge cases. Higher layers should offer access to the lower layers, enabling more complex use cases.