Back to Blog

June 21, 2026

Odoo 19.4 Rips Out Its HTTP Server and Rebuilds It on h11 — Then Pulls the Request Object Out of Every Model

Odoo 19.4 replaces its legacy HTTP server with an h11-based implementation, removes direct request object access from ORM models, and introduces env.website as the new way to access website context inside business logic.

Architecture diagram showing Odoo replacing its legacy HTTP server with h11 and removing the request object from ORM models in favor of env.website

Somewhere deep in the stack that handles every single browser request to an Odoo instance, a change just landed that most users will never notice and most developers will feel immediately. Odoo 19.4 replaces its HTTP server implementation with one built on h11, a pure-Python HTTP/1.1 protocol library. At the same time, the release removes the long-standing request object from the evaluation context of ORM models and introduces env.website as its replacement for website-aware business logic.

These two changes are technically separate commits, but they share a philosophy: stop mixing transport-layer concerns with business logic. The HTTP server handles bytes and connections. The ORM handles records and fields. The two should not be reaching into each other’s pockets.

Why h11, and Why Now

The previous HTTP server in Odoo was a custom implementation that had accumulated years of patches, edge-case handling, and workarounds for protocol quirks. It worked, but it was showing its age — particularly around connection management, keep-alive behavior, and the kind of low-level protocol handling that modern Python libraries handle more reliably.

h11 is a Sans-IO implementation of HTTP/1.1. That means it handles the protocol parsing and state machine without performing any actual I/O itself. It takes bytes in, produces events out, and lets the calling code decide how to read from and write to the network. This separation makes it significantly easier to test, debug, and integrate into different server architectures.

For Odoo specifically, the switch means the HTTP layer becomes a thinner, more predictable component. Protocol parsing is delegated to a well-tested library maintained by the broader Python community, while Odoo’s server code can focus on routing, session management, and application-level concerns. The practical result is fewer mysterious connection drops, cleaner error handling when clients send malformed requests, and a foundation that’s easier to extend if HTTP/2 support ever makes it onto the roadmap.

The Request Object Had No Business Being in Models

This is the change that will break custom modules. For years, Odoo developers have been able to access the HTTP request object from inside model methods. Need to know the current website? Grab it from request. Need the user’s session? Same object. It was convenient, and it was architecturally wrong.

The problem is straightforward: model methods should work regardless of how they’re called. A method on sale.ordershould produce the same result whether it’s invoked from a web controller, a cron job, an XML-RPC call, or a test suite. When that method reaches for the request object, it only works in one of those contexts. The others either crash or silently produce wrong results.

This isn’t theoretical. It’s the source of a specific class of bugs that has plagued Odoo deployments for years: code that works perfectly when triggered from the web interface but fails when the same operation runs from a scheduled action or a queue job. Removingrequestfrom the model evaluation context forces developers to write code that doesn’t depend on the transport layer.

env.website: The Clean Alternative

The most common reason developers reached for requestinside models was to access website context — which website is active, what’s the current domain, which theme is loaded. The replacement is env.website, which provides the same information through the environment object that’s already available in every model method.

The difference isn’t just cosmetic. The environment object (self.env) travels with the recordset. It’s available in every context — web requests, cron jobs, test suites, RPC calls. By putting website context on the environment instead of the request, multi-website logic works correctly regardless of how the code is triggered. A cron that needs to generate website-specific content can set the website on the environment and call the same methods that the web controllers use.

What Breaks and How to Fix It

Any custom module that imports or references request inside a model method will need updating. The migration path is usually straightforward: replace request.website withself.env.website and move any remaining request-dependent logic into the controller where it belongs.

The trickier cases involve code that accesses session data, user agent strings, or IP addresses from within model methods. These genuinely need the request context, and the correct fix is to pass that data as method parameters from the controller rather than reaching for a global object.

It’s a pattern that every web framework eventually enforces. Django did it. Rails did it. Flask’s application context exists specifically to solve this problem. Odoo is catching up to a principle that the rest of the web development world settled years ago: your business logic layer should not know or care about HTTP.

The Bigger Picture for Odoo’s Architecture

These changes arrive alongside three other 19.4 ORM updates: unified access control through a new ir.access model, thread-safe ORM caching with automatic signaling, and deterministic field update ordering via a new write_sequence attribute. Taken together, they represent the most significant backend architectural investment in a single minor release that Odoo has made in recent memory.

The direction is clear. Odoo is cleaning up the boundaries between its layers — HTTP on one side, ORM on the other, with a well-defined environment object carrying context between them. For developers who have been building on top of Odoo, the short-term cost is migration work. The long-term payoff is a platform where business logic is genuinely portable across execution contexts, and where the HTTP server is a replaceable component rather than a load-bearing wall.

Ready to experience Odoo AI?

Join hundreds of teams using DearERP to customize Odoo in minutes, not weeks. Plans start at $29/month.