A framework-agnostic Elixir client for ArcadeDB over the HTTP Cypher command API.
What arcadic is (and is not)
- Is: a thin transport. Sends Cypher/SQL to ArcadeDB's HTTP command API, manages connections and session transactions, normalizes responses.
- Is not: Ash-aware, tenant-aware, or classification-aware. Never put
multitenancy or sensitive-data logic here — that is
ash_arcadic's job.
Public surface
Arcadic—connect/3,with_database/2;query/4+query!/4(idempotent read endpoint),command/4+command!/4(write endpoint),command_async/4(fire-and-forget, returns:okon 202);transaction/3androllback/2for session transactions. Non-bang calls return{:ok, rows}or{:error, %Arcadic.Error{} | %Arcadic.TransportError{}}. Default language is"cypher"; opt intosql/gremlin/graphql/mongo/sqlscriptper call.Arcadic.Conn— a pure-data connection handle (no process). ItsInspectredacts auth and session id.Arcadic.Server— server admin:create_database/2(+!),drop_database/2(+!),database_exists?/2,list_databases/1,ready?/1.- Migrations —
Arcadic.Migration(behaviour:version/0,up/1,down/1),Arcadic.MigrationRegistry(use+migrations [...]),Arcadic.Migrator(migrate/2,status/2,rollback/3,reset/2,pending_migrations/2), tracking applied versions in_arcadic_migrations. Arcadic.Vector— dense + sparse vector search over ArcadeDBLSM_VECTOR/LSM_SPARSE_VECTOR:create_dense_index/5,drop_dense_index/3,neighbors/6,fuse/3,index_ref/2, pluscreate_sparse_index/5,drop_sparse_index/4,sparse_neighbors/8(all +!). Tenant-blind; query vector / tokens / weights /k/ef_search/max_distancebind as params, index refs are identifier-validated, and metadata / query / fusion option inputs are allowlisted and validated value-free. Shared opts onneighbors/sparse_neighbors/fuse:filter(non-empty#bucket:posRID candidate set),group_by(Identifier-shape-guarded),group_size— all param-bound.distancescale is similarity-dependent;fuse/3andsparse_neighbors/8rank byscore(sparse rows carry nodistance). Create sparse indexes before loading rows — they do not retro-index existing data (a[:arcadic, :vector, :sparse_index_preexisting]telemetry event fires if you do).Arcadic.Transport— the transport behaviour seam;Arcadic.Transport.HTTP(Req/Finch) is the default,Arcadic.Transport.Boltis the optional Bolt one.Arcadic.Error/Arcadic.TransportError— the typed error taxonomy.Arcadic.Telemetry— value-free:telemetry.span/3spans.Arcadic.Identifier— allowlist identifier validation.
Bulk loading
- For a large initial load, prefer ArcadeDB's index-deferred bulk import over an
INSERT/CREATE EDGEloop:Arcadic.command(conn, "IMPORT DATABASE '<url>'", %{}, language: "sql")imports CSV / JSON / GraphML / Neo4j / OrientDB exports server-side (the source URL must be reachable by the server). - For batched incremental writes, wrap them in
transaction/3(one commit for many statements) instead of auto-committing eachcommand/4.
Non-negotiable rules
- Parameters only. Every dynamic value goes into the request
paramsmap and is referenced as$namein the statement. Never interpolate a value into a Cypher/SQL string — that is a query-injection defect. This holds forquery/4,command/4,command_async/4, and insidetransaction/3. - Redact at the boundary. Errors and logs carry structure only.
Arcadic.Errorexposes a typedreason,http_status, andexceptionclass; itsdetailfield is quarantined (absent frommessage/1andinspect/1).Arcadic.TransportErrorcarries only the value-free reason atom. Never surface raw parameter values or response rows. - Validate identifiers. Database names and other identifiers reaching a URL
path or statement go through
Arcadic.Identifier.validate/1first (a failure carries the invalid-shape fact only, never the offending string). Values are never identifiers — they rideparams.
Bolt transport (optional)
The Arcadic.Transport.Bolt adapter (optional boltx dependency) runs the query
hot path over Bolt. Start it with Arcadic.Transport.Bolt.start_link/1, which
pins Bolt to v4 (versions: [4.4, 4.3, 4.2, 4.1] — ArcadeDB speaks v4;
boltx defaults to v5), uses the non-TLS bolt scheme (ArcadeDB Bolt is
TLS-disabled by default), and takes username/password. Pass the connection
reference as transport: Arcadic.Transport.Bolt, transport_options: [bolt: ref].
Server admin (create/drop/list database) is HTTP-only — use an HTTP conn for
admin even when queries run over Bolt.
See AGENTS.md for the full working rules and the verified ArcadeDB HTTP contract.