The graph data engine powering HASH
The multi-temporal graph
Where queries are typed programs and database systems are compilation targets
Architecture
hgres consists of three layers:
storage, query/execution and transport
Storage layer
Data inside a graph shouldn’t be untyped. Every field deserves not just a shape, but semantic meaning. hGraph implements semtype’s data model and enforces constraint validation directly in the graph layer, not the application layer.
Multi-TemporalFacts change, and so should data, but what happened before still matters. hGraph tracks every change across two independent time axes, so prior state is always recoverable, never overwritten.
head::entities(temporal_axes) |> body::filter(p -> `https://.../person/v/1` in p.entity_types) |> body::filter(p -> p.properties.`https://.../age` >= 18) |> body::map(p -> ( name: p.properties.`https://.../name`, recent_hr: p.properties.`https://.../heart_rate`, )) |> tail::collectQuery and execution layer
HashQL is the natural extension of semtype. Instead of only typing data, HashQL types queries and brings the same type safety that exists in the application layer to data access. The line between querying and computing dissolves: aggregations, transformations, and filters are all part of the same typed program.
Specialized BackendsData lives in different stores because it should. Time series data belongs in a time series database, not crammed into a relational one. HashQL supports multiple storage backends transparently. The compiler determines which backend handles each part of the query at compilation time and runs placement algorithms to colocate data and computation. No manual annotations required.
Transport layer
Web APIs are untyped by convention. Every service invents its own protocol, its own versioning, its own error model. HaRPC extends the same discipline that semtype brings to data and HashQL brings to queries: typed, versioned interfaces with semantic meaning at the protocol level.
Streaming SessionsHaRPC is stream-based and session-aware, not request/response. A single call can involve back-and-forth between client and server, encoding branching logic as a dialogue within one persistent connection. Subsystems and procedures are semantically versioned, and the protocol treats breaking changes as a first-class part of API evolution, not an accident.
Portable ClientsComplexity lives on the server. The client stays minimal and portable: the same straightforward implementation works in any language that can open a connection. How payloads are serialized is a separate choice entirely.
