Ash DataLayer for Apache AGE graph database.
Stores Ash resources as vertices in an AGE graph within PostgreSQL. Uses the existing Ecto.Repo connection pool — no new database driver. All dynamic values use parameterized queries for safety.
DSL
use Ash.Resource,
data_layer: AshAge.DataLayer
age do
graph :my_graph
repo MyApp.Repo
label :MyLabel # optional, defaults to the module's short name
skip [:computed] # optional, attributes excluded from AGE properties
sensitive [:ssn] # optional, classified attributes (binary-storage or skipped)
rls_guc "myapp.tenant_id" # optional, :attribute-only DB-enforced RLS backstop
# tenant_graph {MyApp.Graphs, :for_tenant, []} # optional, :context graph-name override
edge :related_to do
label :RELATES_TO
direction :outgoing
destination MyApp.OtherResource
end
endCapabilities
Supports :read, :create, :update, :destroy, :bulk_create, :filter
(eq/not_eq/gt/lt/gte/lte/in/is_nil, boolean and nested expressions),
:sort, :limit, :offset, :transact, :multitenancy (:attribute and
:context), :composite_primary_key, and :changeset_filter. Not supported:
:upsert, aggregates, and lateral joins. One subtlety: binary-storage
attributes are unsortable (can?({:sort, :binary}) is false) because
the stored $age64$-tagged base64 form is not byte-order-preserving —
sorting on one raises Ash.Error.Query.UnsortableField at query build.
age
Configuration for the AGE graph data layer
Nested DSLs
Options
| Name | Type | Default | Docs |
|---|---|---|---|
graph | atom | The AGE graph name (must be a valid identifier) | |
repo | atom | The Ecto.Repo module to use for database access | |
label | atom | String.t | Vertex label in the graph. Defaults to the resource's short module name. | |
skip | list(atom) | [] | List of attribute names to exclude from AGE vertex properties |
sensitive | list(atom) | [] | Attribute names classified as sensitive. Fail-closed verifier check (AshAge.DataLayer.Verifiers.ValidateSensitive): each must be binary-storage-typed (app-side-encrypted bytes) or listed in skip. ash_age verifies the type SHAPE — encrypting is the host app's job. Verifier errors are compiler diagnostics; build with --warnings-as-errors to make them blocking. |
tenant_graph | mfa | MFA applied as apply(m, f, [tenant | a]) returning the AGE graph name for a :context tenant. Defaults to a built-in collision-free encoder. | |
rls_guc | String.t | Opt into DB-enforced RLS: the PostgreSQL custom GUC (e.g. "ash_age.tenant_id") ash_age sets per read/write so RLS policies scope by tenant. :attribute only. |
age.edge
edge nameDefines an edge mapping from this vertex to another
Arguments
| Name | Type | Default | Docs |
|---|---|---|---|
name | atom | Relationship name (must match an Ash relationship) |
Options
| Name | Type | Default | Docs |
|---|---|---|---|
label | atom | Edge label in the graph (e.g., :RELATES_TO) | |
destination | atom | Destination resource module | |
direction | :outgoing | :incoming | :both | :outgoing | Edge direction |
properties | list(atom) | [] | Optional edge property keys, set from same-named action arguments. |
Introspection
Target: AshAge.Edge