Inside EnTT: sparse-set storage, optional pointer stability, and the jump to 4.0
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++ library that grew out of an entity component system into runtime reflection, resource management and an execution graph. The storage model and the view syntax are what you have to understand before adopting it, and the 4.0.0 jump arrived without a CHANGELOG file at the top level of the repository.
- Who is it for?
- EnTT fits teams writing C++ that need entity storage with query views and little else: the header-only layout, the sparse set and the pay for what you use policy remove most of the guesswork from a first integration, and the 4.0.0 tag dated 2026-07-23 shows the line is still moving.
- 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 last received commits 2 days ago.
- What is it written in?
- Mainly C++, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on November 13, 2026, and from our analysis. They are not legal advice.
Star history
- skypjack/entt13,267 ★ · +135
| Repository | 2026-09-22 | 2026-11-13 |
|---|---|---|
| skypjack/entt | 13.1k | 13.3k |
135 Stars in the last 52 days, measured from the daily GitHub snapshot. Compare with other projects
Editorial analysis
A sparse set where pointer stability is a setting you opt into
EnTT stores components in a sparse set, and the component types you declare carry no constraints at all. A registry holds plain structs, then a query names the types it wants:
#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>();`registry.view<const position, velocity>()` is the whole query: const access to position, mutable access to velocity, nothing else. The project calls this a pay for what you use policy, where the cost tracks the types you actually touch.
What the view never tells you is whether the addresses behind it stay put. Pointer stability is an option rather than a default, and hooks exist for customizing storage underneath. The consequence for your code is concrete: a raw pointer or reference taken from a registry and cached in another object cannot be assumed to survive an insertion into the same pool, so on an existing codebase the first thing to verify is which mode it enabled. Nothing in the query syntax records that choice for the next reader.
Three iteration shapes over one view, and only two hand you the entity
A view can be walked in several ways, and they give you different things. These three come straight from the example:
// use a callback
view.each([](const auto &pos, auto &vel) { /* ... */ });
// use an extended callback
view.each([](const auto entity, const auto &pos, auto &vel) { /* ... */ });
// use a range-for
for(auto [entity, pos, vel]: view.each()) {
// ...
}The plain callback skips the entity handle, which matters the moment your system keys off it. The extended callback and the range-for both deliver the entity. A fourth form uses forward iterators to hand back only the components of interest, so you get no handle at all unless you ask for one. That choice is cheap for a system that only needs the data and awkward for one that has to write something back later.
What none of the four documents is what happens when a system inserts or removes components mid-loop. The example stays silent on it. If a callback in your code can trigger a structural change, settle that question on your own terms before you spend time profiling anything else.
The benchmark is yours to compile: ENTT_BUILD_BENCHMARK in release mode
The benchmark section is short and pointed. The author says you will never see him trying to make other projects look bad or offering dubious comparisons, and he leaves that activity to others. What is offered instead is a harness you compile yourself: the benchmark test in release mode, to enable compiler optimizations, otherwise it would make little sense, with the `ENTT_BUILD_BENCHMARK` option of CMake set to `ON`.
No frame times, no memory figures and no ranking appear alongside it. For an engineer choosing an entity component system, that puts the evaluation cost on your side of the table. You get the means to measure, not a measurement. Budget time to build it in release mode and run it against the scene you actually have, with your own component types rather than the library's samples.
Treat any vendor table claiming EnTT beats a named library as something to reproduce before you act on it. A project that declines to publish the comparison has usually had a reason, and the reason is rarely flattering to the reader who skipped the build.
CMake, Bazel, Conan and vcpkg all live at the top level, next to single_include
The repository carries four build paths at once. There is `CMakeLists.txt` with a `cmake/` directory, `BUILD.bazel` with `WORKSPACE.bazel`, `MODULE.bazel`, `.bazelrc` and `.bazeliskrc`, `conanfile.py` with `conan/`, and a `single_include/` directory holding the amalgamated form. The overview links the vcpkg port and the Conan Center recipe, and its table of contents has separate CMake, Natvis support, Packaging Tools and pkg-config sections. No copy-paste install command appears in the overview, so take the integration steps from those sections rather than assembling flags yourself.
Having all four is a decision you make once and then pin. Developers building locally with CMake while CI resolves through vcpkg can end up compiling different header contents, and `single_include/` makes that drift easy to miss because both builds succeed. Pick one path, then check which header the build actually included.
Packagers get `conanfile.py` and the Bazel tree to keep in step with each other, and neither is documented in the introduction.
Version 4.0.0 landed on 2026-07-23 with no CHANGELOG file at the top level
The release line moved out of the 3.x series: v3.15.0 on 2025-03-19, v3.16.0 on 2025-11-20, then v4.0.0 on 2026-07-23. The repository is not archived and the last push was on 2026-11-02, so the 4.x line is where new work is going.
What the top level does not contain is a CHANGELOG or an upgrade guide. There is `TODO`, `docs/`, `test/`, `testbed/`, `scripts/` and `AUTHORS`, but nothing recording what a 4.0.0 port touches. The consequence lands hardest on teams upgrading rather than starting fresh, because a major bump following a 3.16.0 line in use for eight months means you read the v4.0.0 tag changes yourself before opening a single file. EnTT is header-only, so a signature change arrives as a wall of compile errors instead of a link failure, and a library this size produces a lot of them at once. Budget for that in a branch of its own.
The author says the API has been copied, so a familiar call site may not be EnTT
The author is blunt about provenance and expects you to recognise the EnTT API from elsewhere, because it has been copied a lot, often without much ado. He also credits EntityX, another C++ library, as the heavy inspiration for the initial design. Two consequences follow for a reviewer.
First, code that looks like EnTT may not be EnTT. A derivative can keep the names while changing what a view, a storage hook or a reflection call actually does, so grepping for `entt::` in a tree does not prove which semantics you have. Check the include path, not the spelling.
Second, EnTT ships a built-in RTTI system mostly similar to the standard one and, alongside it, a non-intrusive macro-free runtime reflection system. A codebase carrying both compiler RTTI and EnTT reflection now holds two ways of asking what a type is, and the overview does not say which one a given code path uses. Decide that per subsystem instead of assuming one reflection story covers the project.
Minecraft and ArcGIS are a name check, not a compatibility table
The adoption claims are names rather than evidence. EnTT is used in Minecraft by Mojang, in the ArcGIS Runtime SDKs by Esri, and in Ragdoll, and the author reads Minecraft being available everywhere as proof that the library has been sufficiently tested on every platform that comes to mind. That is an argument, not a matrix.
The overview states the library targets modern C++ and leaves the compiler and standard version to a Requirements section it never summarizes. No minimum version, no compiler list, no supported platforms appear next to it, and no version of the C++ standard is named in the introduction either. If your toolchain is pinned by a corporate baseline, read that section before you commit, because you cannot infer your standard from the word modern.
The overview also claims all tools are DLL-friendly and run smoothly across boundaries, again with no two-module example to copy. A header-only library that works inside one binary tells you nothing about two, so a service that splits entity code across a DLL or shared library boundary has to verify its own runtime and ABI settings first.
Editorial conclusion
EnTT fits teams writing C++ that need entity storage with query views and little else: the header-only layout, the sparse set and the pay for what you use policy remove most of the guesswork from a first integration, and the 4.0.0 tag dated 2026-07-23 shows the line is still moving. Leave it if you need the standard RTTI path only, if your design caches pointers into a registry without knowing which mode you enabled, or if your build has to be reproducible from one documented command, because the repository ships CMake, Bazel and Conan files and no CHANGELOG. Before adopting, compile the benchmark test with the ENTT_BUILD_BENCHMARK option of CMake set to ON in release mode and measure it against your own scene, since the project publishes no comparison numbers of its own.
Frequently asked questions
What is EnTT used for in C++?
EnTT is a header-only C++ library for game programming, built around the entity component system pattern. The project says it is used in Minecraft by Mojang, in the ArcGIS Runtime SDKs by Esri and in Ragdoll, and that its scope now reaches past a pure ECS to a built-in RTTI system, an execution graph builder, resource management and a tiny event dispatcher.
What is an entity component system in C++?
It is an architectural pattern used mostly in game development, where entities are identifiers and components carry the data. EnTT started as a pure entity component system and grew by adding classes and functionality around it.
Is EnTT still being worked on?
The repository is not archived and the last push was on 2026-11-02. The most recent release is v4.0.0 from 2026-07-23, which followed v3.16.0 from 2025-11-20 and v3.15.0 from 2025-03-19.
What license does EnTT use?
EnTT is released under the MIT license, with a single LICENSE file at the top level of the repository and a separate AUTHORS file for contributors.
Can EnTT be used outside games?
The project positions itself for game programming and much more, and reports use in the ArcGIS Runtime SDKs by Esri. Beyond the ECS core it lists an execution graph builder, a macro-free runtime reflection system, resource management with cache, loaders and handles, delegates and signal handlers, plus homemade containers such as a sparse set based hash map.
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)Star history chart for your README
[](https://hysenlabs.com/projects/skypjack-entt)Was this useful?