Otoroshi 18 · Part 1 of 1
Otoroshi 18 is here: new foundations, same gateway
The biggest overhaul of Otoroshi in years, designed to be the most boring upgrade you will do this year.

On October 23, we released Otoroshi 18.0.0, followed three days later by 18.0.1. It is the most significant release in years, and probably the best prepared: the entire technical foundation was replaced, Service Descriptors are finally gone, and the gateway went through two full security audits.
Yet for the vast majority of installations, the upgrade should be perfectly boring. Your routes, plugins, API keys, certificates and exporters stay as they are. Your traffic does not notice a thing.
This post opens a series of seven about Otoroshi 18 and what we built around it. We start with the big picture.
Why the foundations had to change
Otoroshi ran on Scala 2.12, Play 2.8 and Akka 2.6. Each of these building blocks had a problem:
- Scala 2.12 dates from 2016. Fewer and fewer libraries still publish for it.
- Akka was relicensed under the BSL in September 2023. The Apache Software Foundation took over the last Apache 2.0 release under the name Apache Pekko, and the ecosystem followed.
- Play 2.8 is no longer maintained, and Play 3, the Pekko-based line, came out in late 2023.
Taken one at a time, each of these is manageable. Together, they were pulling Otoroshi away from the rest of the JVM ecosystem, a little more every month. The issue asking for the move to Play 3 was opened in November 2023.
The port started in June, and in early July we froze features to focus on it entirely. The rule was strict: change the foundations, and nothing else.
What changed under the hood
| Before | After |
|---|---|
| Scala 2.12 | Scala 3.8 |
| Play 2.8 | Play 3.0 |
| Akka 2.6 | Apache Pekko 1.6 |
| Java 11 minimum | Java 17 minimum |
| Admin UI built with webpack, jQuery | Vite, no more jQuery |
| Patched, vendored third-party libraries | Back on the official releases |
Pekko is a direct fork of the Akka we were already running: same actor model, same streams, same HTTP stack. The package names change, the behavior stays the same.
What goes away: Service Descriptors
Service Descriptors had been deprecated since February 2022, when the new proxy engine landed. Version 17 shipped the migration tooling. Version 18 removes the entity, its admin API, its UI pages and its Kubernetes CRD. Routes are now the only way to configure HTTP proxying: one entity, one mental model, one code path.
Nobody has to migrate anything by hand. On first startup, a job backs up every descriptor to a file, then converts it to a Route, keeping the same id. A descriptor is only deleted once its Route has been written and read back. Anything that fails is left in place, logged, and retried at the next startup. API keys that pointed to an old service keep working.
What comes on top
Once the port was validated, we lifted the freeze. The following previews brought new features that make a real difference for teams that publish APIs:
- Every API consumer becomes an API key, whatever the plan (no authentication, JWT, mTLS, OAuth2). Quotas, rate limiting and analytics apply to every caller.
- Plugin chains per consumer: a plan or an API key can bring its own plugins, on top of the route’s or in place of them.
- Conditional plugins: any plugin can run only when conditions are met on the key, the user, the route, the request or the response.
- Trusted proxies: the client address is read from the trusted end of the
X-Forwarded-Forchain. A client can no longer pick its own IP to get around a rate limit. - A faster hot path, and a JVM sized automatically from the container limits.
We will cover all of this in detail in the next posts, starting with performance.
Check, then check again
A port of this size is only as good as the checks behind it. We spent at least as much time verifying as writing.
| The project in numbers | |
|---|---|
| Duration, from the first commit of the port to the release | just over 4 months |
| Commits | about 1,000 |
| Issues closed | 234 |
| Test versions published | 9 previews, 4 release candidates |
| Lines of tests added | more than 70,000 |
| Full security audits | 2 |
The test suite now covers clustering, mTLS, WebAuthn, SAML validation and the rights of the admin API. It writes and reads back the JSON of every entity and every plugin configuration. That test alone turned up dozens of settings that lost their value on save. None of them would have shown up in a demo, and all of them are fixed.
The OpenAPI document of the admin API was rewritten, and a conformance suite now checks it against a running Otoroshi. Every disagreement was a bug on one side or the other, and it was fixed where it belonged.
Who is behind it
Otoroshi has been open source since day one, in 2017, under the Apache 2.0 license. Cloud APIM was founded in 2021 by its creator, and today most of its development is done by us: of the roughly 1,000 commits in version 18, more than 800 come from the Cloud APIM team. Thanks also to everyone who contributed code, tested the previews and reported bugs.
On release day, we also published three extensions compatible with Otoroshi 18: the LLM extension and its AI Studio, the Threat Protection suite and its Threat Studio, and the brand-new Clever Cloud Reaper. Each one gets its own post in this series.
What now?
For most installations, the answer fits in one sentence: upgrade to 18. A few points are still worth a look first:
- Java 17 minimum.
akka.*settings becomepekko.*(theOTOROSHI_AKKA_*environment variables keep working).- In-house Scala plugins must be recompiled for Scala 3. WASM plugins are not affected.
- On Kubernetes, apply the new CRDs.
The 17.x line remains available for those who need more time. And if you would rather not think about it at all, our Otoroshi Managed clusters are upgraded by the team that writes the code.
Further reading
- The full technical post on the Otoroshi blog
- The 18.0.0 release notes
- The Service Descriptors migration guide
- The production checklist
Next post: what we measured, and what we gained in performance.


