SurrealDB supports ISO/IEC 39075 GQL for graph pattern matching and data modification over your existing tables and RELATE edges. The surface syntax is closer to Cypher-style MATCH … RETURN than to SurrealQL SELECT, but it runs on the same storage model: node labels map to tables, edge types map to relation tables, and properties map to record fields.
GQL is experimental in 3.2. Enable it at server start with --allow-experimental gql (or SURREAL_CAPS_ALLOW_EXPERIMENTAL=gql). The surface includes read queries (MATCH … RETURN) and data-modifying statements (INSERT, SET, REMOVE, DELETE) — see GQL mutations.
GQL is not GraphQL
SurrealDB exposes two different graph query languages on separate endpoints. Do not abbreviate GraphQL to gql in product identifiers — the short name gql refers to ISO GQL only.
| GQL (this guide) | GraphQL | |
|---|---|---|
| Standard | ISO/IEC 39075 GQL | GraphQL |
| Syntax | MATCH (a)-[:knows]->(b) RETURN … | query { people { name } } |
| HTTP | POST /gql | POST /graphql |
| WebSocket RPC | method: "gql" | method: "graphql" |
| Setup | Experimental capability gql | DEFINE CONFIG GRAPHQL |
| Schema | Tables and RELATE edges you already have | Auto-generated GraphQL schema from your database |
When to use GQL
You already think in graph patterns such as
(a)-[:knows]->(b),SHORTEST, andALL SHORTEST, and have yet to learn how to query such paths in SurrealQL.You are migrating a database from Neo4j to SurrealDB and want to test to ensure that existing Cypher queries map to the same output.
You want a stable graph query surface aligned with the ISO GQL standard.
For general-purpose schema changes, bulk load, and full SurrealQL expressiveness, keep using SurrealQL and the /sql endpoint. For ISO graph-pattern writes (INSERT, SET, REMOVE, DELETE), see GQL mutations.
Wire surfaces
Session headers match /sql: Surreal-NS, Surreal-DB, and authentication. Responses use the same JSON envelope as /sql (status, result, time).
Try from SurrealQL (eval::gql)
To experiment in the REPL without curl or POST /gql, wrap a GQL string in eval::gql. The function runs the same engine as the HTTP endpoint and participates in the caller's transaction (including mutations).
eval::gql needs two capability gates that --allow-all does not enable:
gql—--allow-experimental gqleval—--allow-eval-query(denied for every subject by default)
Embedded REPL (surreal sql against memory or a file path — no separate surreal start):
surreal sql --user root --pass secret \
--allow-experimental gql --allow-eval-queryeval::gql("MATCH (n:person) RETURN n.name AS name ORDER BY name");Remote server (surreal start + surreal sql -e ws://…): pass both flags on surreal start only. The client REPL does not enable eval at runtime.
surreal start --user root --pass secret \
--allow-experimental gql --allow-eval-queryOptional bindings use an object as the second argument: eval::gql("… WHERE n.age > $min …", { min: 18 }). Full setup, seed data, and more examples can be found on the Eval functions page.
Data model mapping
| GQL | SurrealDB |
|---|---|
(:person) | Rows in table person |
-[k:knows]-> | Rows in relation table knows (in / out record IDs) |
n.name | Field name on the bound record |
$min | Parameter — bind via RPC params object (typed JSON values) |
GQL is not lowered to SurrealQL text — it compiles to an internal match plan and runs on the streaming engine. The sample queries page shows SurrealQL that returns the same shape where a close equivalent exists; some patterns (optional match blocks, path selectors) are much more concise in GQL.
Notable syntax differences from openCypher
--starts a line comment, not an undirected edge.Inequality is
<>, not!=.Label conjunction uses
&(:person&employee), not:person:employee.Variable-length quantifiers are postfix on the edge:
-[e:knows]->{1,3}(b), not*1..3inside the brackets.No
INlist membership operator in this subset.
Design notes, the supported subset, and mutation semantics are documented in the SurrealDB source tree under doc/opengql/ (REFERENCE.md, LOWERING.md). The parser grammar is vendored from the upstream opengql/grammar project; that name refers to the grammar repository, not the ISO standard SurrealDB implements.
Next steps
GQL via HTTP — enable GQL, load data, and call
POST /gqlwith cURL oreval::gqlfrom the REPLGQL mutations —
INSERT,SET,REMOVE,DELETEPOST /gqlHTTP reference — headers, response envelope, and parametersSample GQL and SurrealQL queries — side-by-side examples on the seed graph
Eval functions — run GQL from inside SurrealQL with
eval::gql