HashQL HashQL, a hypergraph query language supporting multiple independent time dimensions, was released as a research preview. Developed by the hgres team, it combines temporality, typing, and graph structure as first-class features, enabling reasoning over data evolution and knowledge timing. The language uses a traversal-based approach and static typing to avoid computational infeasibility common in existing query languages. A hypergraph query language that supports multiple, independent time dimensions — enabling reasoning over how data evolves and when it was known May 20th, 2026 Yesterday we introduced hgres /blog/announcing-hgres . Today we're releasing the first research preview of Building hgres put us in an awkward spot. It sits at the intersection of three things that are usually kept apart: No existing query language gives you all three at once. The usual workaround is to bolt them on through extensions or to glue a couple of languages together with application code; however both options leak abstractions, temporal axes tend to get lost, and queries that sound simple become computationally infeasible. HashQL exists because we needed a single language in which temporality, typing, and graph structure are all first-class — not merely hacky extensions on top of something else. HashQL is a statically typed, functional query language. Whereas most query languages produce strings that databases parse and plan at runtime, HashQL queries are programs that go through a compiler — either at query time or ahead of time — which lets us apply the same techniques you'd expect from any other compiled language to reason about a query's structure before any of it executes. At its core HashQL has a type system that extends SemType https://semtype.org with closures, unions, intersections, and generic containers. It's structural by default https://hgres.org/hashql/type-system in the TypeScript sense, with nominal typing available through newtypes — no branded types, no awkward indexing tricks. A Hindley-Milner style inference engine over subtyping constraints handles the bookkeeping, so most queries need no annotations at all; the compiler derives types from usage. Normal declarative query languages express traversals through pattern matching, turning every query into a subgraph isomorphism problem. These become difficult to deal with once adding multiple time axes, with temporal traversals hard to express clearly in terms of patterns. HashQL takes a traversal-based rather than declarative approach, similar to that found in the Gremlin https://tinkerpop.apache.org/gremlin.html query language, helping us avoid these problems: every traversal is just a sequence of calls to traversal operators, and a query is just a program. In HashQL you describe the traversal directly: start from a set of entities, filter, transform, follow links, aggregate. php head::entities temporal axes | body::filter entity - https://.../person/v/1 in entity.entity types | body::filter entity - entity.properties. https://.../age 30 | tail::collect head::entities establishes the temporal slice and vertex type. Each body::filter closure receives a typed entity value and returns a boolean. The compiler verifies that the property paths exist on the declared type and that the comparison is valid. tail::collect materializes the result. Because closures are first-class, predicates compose and transformations are reusable... with aggregations, transformations, and filters all forming part of the same typed program, with no separation between the querying language and that used to compute over the results. All interaction with the graph is isolated by the effect type Graph