Most explanations of Odoo Enterprise versus Community are sales documents: a two-column table of features. That table is useless to an engineer, because it answers "what does the customer get?" and not "what will my module assume?" The edition boundary is not a feature list. It is a technical line that runs through view types, whole functional domains, and the web client itself. A module built without thinking about it can break silently when deployed on the other side.
View types are the sharpest edge
Community ships a fixed set of view types: form, list, kanban, calendar, graph, pivot, activity. Four more exist only in Enterprise: Gantt, Cohort, Map, and Grid, delivered by the web_gantt, web_cohort, web_map, and web_grid modules.
This is the boundary engineers cross without noticing. You build a model, you add a <gantt> view because the scheduling UX is perfect for it, it works flawlessly in your Enterprise development database. Deployed to a Community instance, the action that opens that view has no renderer for it. The feature doesn't degrade gracefully. It fails. A view type is a hard dependency, not a nice-to-have.
Whole functional domains have no Community equivalent
It is not just views. Entire application areas are Enterprise-only: Helpdesk, Planning, Subscriptions, Documents, Sign, Studio, and the full IoT stack. There is no Community version of these. Not a reduced one, none.
The trap is the bridge module. If your custom code integrates with Helpdesk (extends helpdesk.ticket, reacts to its events) then your module depends on helpdesk, and it simply will not install on a Community database, because helpdesk isn't there to depend on. That is correct behaviour, but it needs to be a decision you made, not a discovery you make at deployment.
AI is the newest stretch of the boundary
Odoo 19 added an entire AI layer: fourteen modules built around an ai.agent orchestration model, embeddings for retrieval, knowledge sources, and AI-driven server actions. All of it is Enterprise. Community Odoo has no AI capability at all. If a feature you are scoping leans on Odoo's built-in AI, that feature has just made the whole deployment Enterprise-only, a licensing fact worth surfacing in design, not in delivery.
The web client itself differs
The boundary even runs through the shell. The web_enterprise module replaces Community's web client entry point. It brings the home menu with its app grid, enterprise theming, the dark-mode infrastructure, and enhanced renderers. Front-end customizations that assume the enterprise web client's structure, styling hooks, or dark-mode variables are themselves implicitly Enterprise-only, even when nothing in the Python layer says so.
Building modules that respect the boundary
The discipline is not complicated; it just has to be deliberate:
- Declare dependencies honestly. If your module needs a Gantt view, it depends on
web_ganttand is therefore an Enterprise module. Own that in the manifest rather than hoping. - Isolate edition-specific code in bridge modules. Keep the core module edition-neutral; put the Helpdesk integration, or the Gantt view, in a separate module that depends on the Enterprise piece. A Community customer installs the core; an Enterprise customer installs both.
- Know your deployment target before you design. "Which edition is this customer on?" is a question that belongs at the start of scoping, not at the end. It silently determines which view types, modules, and AI features are even on the table.
- Test on the edition you ship to. A module verified only on Enterprise has not been verified for a Community customer. The boundary is exactly the kind of thing that passes every test until it is deployed across it.
The Enterprise/Community question is usually framed as commercial: what does the licence cost, what does the customer get. For an engineer it is architectural: it decides what your code is allowed to assume exists. Treat it as a design input from day one, and the boundary is just a constraint. Discover it at deployment, and it is an outage.