π Typhon π
Overview: An Embedded ACID Database Engine With ECS Architecture
Typhon is an embedded database engine that takes the architectural patterns that make game engines fast β Entity-Component-System, data-oriented design, cache-line awareness β and applies them to build an ACID database from first principles. It targets 1β2 microsecond transaction commits in C#/.NET.
The thesis: game engines and databases are solving the same fundamental problem (managing structured data with performance constraints) but evolved completely different solutions. Typhon combines both β ECS storage with MVCC transactions, SIMD-optimized data access with WAL durability.
Status: Early alpha β the engine is functional with working MVCC, WAL, crash recovery, B+Tree indexes, and query engine. Not yet available for external use.
Core Features
Component-Based Architecture
Data is organized into typed, blittable components grouped by archetypes β the ECS model, applied to a database. Components must be unmanaged structs with explicit layout, enabling zero-copy reads and SIMD-friendly memory access.
[Component("Game.PlayerPosition", 1)]
[StructLayout(LayoutKind.Sequential)]
public struct PlayerPosition
{
[Field] public float X;
[Field] public float Y;
[Field] public float Z;
}
[Archetype(100)]
class PlayerArch : Archetype<PlayerArch>
{
public static readonly Comp<PlayerPosition> Position = Register<PlayerPosition>();
}
MVCC Transaction System
All operations go through a three-tier API: DatabaseEngine (setup) β UnitOfWork (durability boundary) β Transaction (MVCC operations).
- Snapshot isolation β readers see a frozen point-in-time, never block writers
- Per-component revision chains β updating 1 component on an 8-component entity creates 1 revision, not 8
- Conflict detection at commit β optimistic concurrency with application-defined merge strategies
- Three durability modes per UnitOfWork:
- Deferred (~1β2 Β΅s commits) β data volatile until explicit Flush()
- GroupCommit (~1β2 Β΅s + auto-flush every N ms) β amortized durability
- Immediate (~15β85 Β΅s commits) β FUA write on every commit, zero data loss
Deadlock-Free by Construction
Typhon makes deadlocks structurally impossible through a three-pillar design:
- MVCC eliminates inter-transaction locks β readers see snapshots, writers create revisions, no data-level locks
- Optimistic Lock Coupling β B+Tree traversal without holding latches (version-counter validation instead)
- No cross-table latch holding β operations on different component tables are independent
No deadlock detection, no timeouts, no victim selection β deadlocks cannot form. The cost is optimistic retries on conflict, which is a local cost vs the global cost of cycle detection.
Three Storage Modes
Choose the right trade-off per component:
- Versioned β Full MVCC snapshot isolation, WAL per-transaction, crash recovery to exact pre-crash state. For data that demands ACID guarantees.
- SingleVersion β In-place writes (last-writer-wins), tick-fence WAL durability, crash recovery to last tick boundary. For high-frequency updates where the latest value is all that matters (e.g. NPC positions).
- Transient β Heap memory only, no persistence, no WAL, all data lost on crash. For ephemeral state like physics scratch buffers.
High-Performance Storage Engine
- GCHandle-pinned page cache β the GC never moves, scans, or pauses the hot data
- SIMD Vector256 chunk accessor β 16-slot MRU cache with parallel search, three-tier hot path (MRU β SIMD β clock-sweep eviction)
- Epoch-based page protection β 2 operations per transaction instead of 2N for reference counting
- Zero-copy reads β
EntityRefis a 96-byteref structthat returnsref readonly Tdirectly into pinned page memory - Hardware-accelerated CRC32C β SSE4.2 on x64, ARM CRC32C on ARM64, software fallback
Indexing
B+Tree indexes with SIMD-accelerated search, automatically maintained on component fields:
[Component("Game.Enemy", 1, StorageMode = StorageMode.SingleVersion)]
[StructLayout(LayoutKind.Sequential)]
public struct Enemy
{
[Field] [Index(AllowMultiple = true)]
public int ZoneId;
[Field]
public int Health;
[Index(AllowMultiple = true, OnParentDelete = CascadeAction.Delete)]
public EntityLink<PlayerArch> Owner;
}
B+Tree nodes are 256 bytes (four cache lines), with Vector256.LessThan for parallel key comparison. Measured: 267 ns per lookup, 3.7M ops/sec.
Compile-Time Safety via Roslyn Analyzers
A custom analyzer suite (TYPHON001β007) enforces domain-specific safety rules as compiler errors:
[NoCopy]β performance-critical structs cannot be passed by value (must useref)- Ownership tracking β undisposed
ChunkAccessororTransactionis a compiler error, not a runtime leak - Disposal completeness β
Dispose()methods that miss critical fields or have early returns are caught at build time
Use Cases
Typhon is designed for workloads that need both real-time performance and transactional safety:
- Persistent game servers β ACID transactions at game-tick speeds
- Simulation engines β high-frequency entity updates with durability when it matters
- Real-time systems β any domain where microsecond latency and data integrity must coexist
Technical Foundation
Built entirely in C# on .NET 10, using:
- Hardware intrinsics (
System.Runtime.Intrinsics) β SSE4.2, ARM64 CRC32, Vector256 SIMD ref structfor zero-allocation hot paths β EntityRef, EpochGuard, ChunkAccessor- Constrained generics (
where T : unmanaged) β JIT monomorphization, compile-timesizeof(T) [StructLayout]β exact memory layout control, cache-line alignment, false-sharing prevention- Roslyn analyzers β compile-time ownership and copy safety
- BenchmarkDotNet β rigorous micro-benchmarking with regression tracking
Why?
Initially I wanted to βmake a database engine for MMOs, something fast, reliable and scalableβ (in that order).
The deeper insight came later: game engines (ECS) and databases solve the same fundamental problem β managing structured data under performance constraints β but evolved completely different solutions. ECS optimized for throughput on bulk operations. Databases optimized for flexibility and isolation. Typhon argues you can have both.
Fast
In the realm of the microsecond. A full CRUD lifecycle (spawn, read, update, destroy, commit with MVCC) measures at 1.2 Β΅s. The bottleneck is memory access patterns, not the language.
More suitable
Adopting ECS principals makes the data model natural for game developers β entities gain/lose components at runtime, no ALTER TABLE, no migration scripts. Components are blittable structs with zero-copy access.
Reliable, meaning Durable (or notβ¦)
Atomic, transaction-based and durable operations. Through a design decision, the user can choose durability per component (Versioned/SingleVersion/Transient) and per transaction (Deferred/GroupCommit/Immediate override).
History
This project went through many things:
- Bootstrapped in 2015 with a very different design and intent, then quickly put on a shelf.
- Resurrected during COVID in 2020 as a POC of βis it possible to make a real-time ACID database, down to the Β΅sβ, oriented for persistent games? Then put on a shelf after promising work.
- Many concepts around unsafe/GC-free .net programming lead me to develop π , but the two projects are not dependent. I, for once, successfully restrained myself to retrofit π into this one, itβs totally doable, but as usual, just a matter of timeβ¦
- Re-resurrected in summer 2025 with the βfirm, but fragileβ intention to reach an alpha stage.
- 2025β2026: reached early alpha β working MVCC, WAL with crash recovery, B+Tree indexes, query engine, three storage modes, three durability modes, custom Roslyn analyzer suite, and a comprehensive benchmark/regression tracking pipeline.