EnTT: a header-only C++ entity component system you can drop into an existing engine
Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more
At a glance
- What is it?
- EnTT is a header-only C++17 library from skypjack that provides an entity component system plus reflection, an event dispatcher and a scheduler. This review covers how the registry and views work, how to integrate it with CMake, and where the pay-for-what-you-use design becomes a liability.
- Who is it for?
- EnTT fits teams already writing modern C++ who want an ECS they can include without adding a build dependency or a runtime: the registry, views and groups are the core, and everything else in the library is optional. It is the wrong choice if you need a full engine with an editor, asset pipeline and serialization, since the README lists resource management and reflection facilities but not a toolchain around them.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository received new commits within the last day.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What EnTT actually solves for a C++ codebase
EnTT targets the structural problem that appears once a game or simulation has more than a handful of object types: inheritance hierarchies stop scaling when behaviour needs to be recombined, and hand-rolled arrays of structs make it hard to iterate only the objects that have a given set of properties. The entity-component-system pattern replaces that with entities as identifiers, components as plain data attached to them, and systems that query for the combination they need. EnTT's README frames the library as "a header-only, tiny and easy to use library for game programming and much more written in modern C++", and the pattern is the core of it.
The audience is narrower than the topic list suggests. This is a library for people who are already comfortable with templates, because the API is built on them: the README's own example defines position and velocity structs and then calls registry.view<const position, velocity>(). Nothing about the design hides the template machinery from you. If your team writes C++17 and wants an ECS that compiles into the same binary as the rest of the engine, with no separate runtime and no code generator, that is the gap EnTT fills. The README also notes the library is used in Minecraft by Mojang and in the ArcGIS Runtime SDKs by Esri, which is a statement about where it has been deployed rather than a guarantee about your workload.
The registry, views and groups: how the data flow works
The central object is entt::registry. Entities are created through registry.create(), components are attached with registry.emplace<T>(entity, args...), and iteration happens through views. The README's example creates ten entities, gives every one of them a position, and gives velocity only to the even-numbered ones, then iterates with a view over const position and velocity. The view returns only entities that have both components, so the odd entities are skipped without a branch in user code.
That query is the mechanism worth understanding before adopting. A view is not a copy of your data; it is an iterator over the intersection of the component storages involved. The README describes views and groups as the two access patterns the library offers, ranging from "perfect SoA" to fully random, and it says component types are unconstrained with optional pointer stability and hooks for storage customization. Those three words describe the real trade-off. Pointer stability is optional, which means the default storage can move components around as entities are added and removed. Code that keeps a raw pointer or reference to a component across a structural change is relying on a property the library treats as a choice, not a default.
The README lists four iteration styles in one example: a callback through view.each, an extended callback that also receives the entity, a range-for over view.each() with structured bindings, and a plain range-for over the view with a later view.get<velocity>(entity). They are not equivalent in cost. The last form walks the view and then does a second lookup per entity, while the callback forms hand you the components directly. For a hot loop, that difference is the one to measure.
Integrating EnTT with CMake and iterating a first view
The README's integration section names CMake, Natvis support, packaging tools and pkg-config as the supported routes, and lists Requirements before them. Because the library is header-only and has no dependencies, the practical move is to make the headers visible to your compiler and include <entt/entt.hpp>. The repository also ships single_include/, conanfile.py, a vcpkg port badge and BUILD.bazel, so Conan, vcpkg and Bazel users have their own entry points.
The README's own code example is the shortest thing that shows the data flow end to end:
#include <entt/entt.hpp>
struct position {
float x;
float y;
};
struct velocity {
float dx;
float dy;
};
void update(entt::registry ®istry) {
auto view = registry.view<const position, velocity>();
// use a callback
view.each([](const auto &pos, auto &vel) { /* ... */ });
// use a range-for
for(auto [entity, pos, vel]: view.each()) {
// ...
}
}What you should see is a program that compiles and runs with no output; the callback body is where your integration step goes. If it fails to compile, the first thing to check is the language standard, since the README places EnTT in the modern C++ category and the topics list names cpp17 and cpp20.
Where EnTT is the wrong tool, and what pointer stability costs you
The clearest limitation is scope. EnTT is a library, not an engine. The README's list of features includes an RTTI system, resource management with cache, loaders and handles, an execution graph builder, a service locator, reflection, a cooperative scheduler and an event emitter, but it presents all of them as facilities built on top of the entity-component system. There is no editor, no scene format and no asset pipeline in that list. If your project needs those, EnTT is a component you build around, not a replacement for the thing you were going to buy.
The second limitation is the one that bites in practice: optional pointer stability. The README states that component types are unconstrained "with optional pointer stability and hooks for storage customization". Optional means the default storage is free to relocate components when the registry changes shape. Any code holding a reference into a component across an emplace, a destroy or a view-driven structural change is making an assumption the library does not make for you. The same applies to storage customization: swapping in a custom storage changes the guarantees your code can rely on, and the README does not enumerate what those guarantees are.
There is also an API-surface cost. The README says the library "started off as a pure entity-component system" and that the codebase grew as more classes and functionalities were added, and it calls the feature list a work in progress. A large, template-heavy header-only library is a compile-time cost in every translation unit that includes it, and the single-include variant exists for a reason. If your build is already slow, adding EnTT to a widely included header is a decision to make deliberately.
EnTT versus Flecs: two answers to the same question
Flecs is the comparison people reach for, and the two libraries differ in where they put the weight. EnTT's README describes the project as header-only with no dependencies, and its feature list is a set of independent facilities: the ECS core, then reflection, a scheduler, resource management and an event emitter alongside it. The ECS is the centre and the rest is optional.
Flecs takes the other route. It is a full ECS runtime with a query language and a broader built-in feature set, which means more of the system design is decided for you and more of it lives in the library rather than in your code. That is a real difference in approach, not a quality ranking: EnTT asks you to assemble the surrounding pieces yourself and gives you a smaller surface to learn, while Flecs gives you more of the architecture up front.
The practical way to choose is to look at the code you already have. If you have an engine loop, an event system and a resource cache, EnTT slots in as the entity storage and leaves the rest alone. If you are starting from an empty directory and want the ECS to come with its own query and scheduling model, the amount of scaffolding EnTT leaves to you is the deciding factor. The README does not offer a migration path between the two, and neither library's documentation should be read as promising one.
Maintenance, upgrades and the MIT licence
The repository is not archived, and the last push was on 2026-09-21. The most recent release is v4.0.0 from 2026-07-23, following v3.16.0 in 2025-11-20 and v3.15.0 in 2025-03-19. That release cadence matters for upgrade planning: the jump from the 3.x line to 4.0.0 is a major version, and the README says nothing about an upgrade guide or a deprecation policy. Anyone pinning EnTT should read the release notes for v4.0.0 rather than assuming the 3.x code in a tutorial still compiles.
Because the library is header-only, there is no binary ABI to reconcile, but that is not the same as a free upgrade. A header-only dependency is recompiled into your project, so a major version change can surface as compile errors across every translation unit that includes entt/entt.hpp, and the README's own note that all tools are DLL-friendly and run smoothly across boundaries is a statement about the library's design, not a compatibility promise between versions.
The licence is MIT, which is permissive and places few obligations on how you redistribute the library. This is not legal advice; the repository's LICENSE file is the text that governs, and the usual step is to have someone who can read it confirm how it interacts with your own distribution model.
Editorial conclusion
EnTT fits teams already writing modern C++ who want an ECS they can include without adding a build dependency or a runtime: the registry, views and groups are the core, and everything else in the library is optional. It is the wrong choice if you need a full engine with an editor, asset pipeline and serialization, since the README lists resource management and reflection facilities but not a toolchain around them. Before adopting, verify two things in your own tree: that your compiler meets the C++17 requirement stated for integration, and that the component types you plan to store behave correctly under the storage hooks you configure, because the library documents storage customization but says nothing about migrating a registry between two of its own versions.
Frequently asked questions
What does EnTT mean?
The README does not expand the name into words. It presents EnTT as the project name and the library as a header-only C++ entity component system and more, so treat the acronym as a label rather than an abbreviation with a documented meaning.
What is EnTT used for in C++?
It provides an entity-component-system architecture for game programming and other work, plus facilities built on top of it: reflection, a cooperative scheduler, resource management, an event emitter and an execution graph builder. The README states it is used in Minecraft by Mojang and in the ArcGIS Runtime SDKs by Esri.
What is an entity component system in C++?
It is an architectural pattern used mostly in game development, in which entities are identifiers, components are plain data attached to them, and systems iterate the combinations they need. EnTT implements it through entt::registry, which creates entities, attaches components and exposes views over them.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/skypjack-entt)