CONCEPT Cited by 1 source
Direction-agnostic edge ID¶
A direction-agnostic edge ID is an edge identifier constructed deterministically from the pair of endpoint node IDs in a way that produces the same identifier regardless of which direction the user requested the traversal. The canonical construction: lexicographically sort the source and destination node IDs, then concatenate them.
edge_property_id = sort([source_id, target_id]).concat()
= lower(source_id, target_id) || higher(source_id, target_id)
Why it matters¶
In a graph storage system that uses
forward and reverse edge
indexes on the link namespace, an edge between nodes A and
B is physically written twice on the link side (once at
forward partition A, once at reverse partition B).
Edge properties, by contrast, are direction-symmetric — a
property of the edge is the same property whether the caller
traversed A → B or B → A. Storing the property bag twice
would mean every property update needs to write to two records
atomically; storing it under one of the two endpoints would
break the symmetry.
The direction-agnostic ID makes the property record single- copy: lex-sorting the endpoints before concatenation gives a unique-and-stable identifier per edge-pair. Properties are indexed once in the property namespace, and either direction reaches them via the same deterministic key.
The verbatim disclosure¶
"To ensure consistent record identifiers when updating edge properties in either direction, the Abstraction lexicographically sorts and concatenates the source and destination node IDs to create a direction-agnostic identifier for property storage. This ensures that properties can be accessed or mutated in a single database call regardless of the direction specified in the request." (Source: sources/2026-05-29-netflix-high-throughput-graph-abstraction-at-netflix-part-i)
Construction example¶
| Caller-requested edge | Lex-sorted endpoints | Concatenated ID |
|---|---|---|
profile-A → device-X |
[device-X, profile-A] |
device-X\|profile-A |
device-X → profile-A |
[device-X, profile-A] |
device-X\|profile-A |
account-Z → profile-A |
[account-Z, profile-A] |
account-Z\|profile-A |
Both directions of the (profile-A, device-X) edge yield the
same property ID. A point read on the property namespace
returns the property bag in a single partition lookup
regardless of how the traversal came in.
Composition with other patterns¶
The direction-agnostic ID composes with:
- patterns/separate-edge-links-from-properties — the prerequisite that puts edge properties in their own namespace.
- patterns/forward-and-reverse-adjacency-index — the forward and reverse link namespaces use the natural endpoint-keyed IDs, while the property namespace uses the direction-agnostic ID. Two different ID strategies for two different namespace classes.
- Last-Write-Wins via timestamped idempotency tokens — property updates from either direction land at the same partition, so LWW resolution happens against a consistent identifier.
When the natural ID would have failed¶
If properties were stored with a natural directional ID like
source||target, then a property update issued from the
reverse-direction traversal (target||source) would land at a
different partition. Two options to fix this without
direction-agnostic IDs would each break:
- Store properties under both natural IDs — doubles property storage, requires atomic two-partition writes for every update (unsolved without distributed transactions or another entropy-repair pipeline).
- Force callers to always use the canonical direction — leaks a storage detail into the API surface; bidirectional edges have no natural canonical direction.
The lex-sort-then-concat construction sidesteps both issues by making the canonical direction a function of the ID values, unique per pair, and stable across calls.
Trade-off¶
The direction-agnostic ID is opaque to humans and not directly
useful as a foreign key — applications that want to retrieve an
edge by (source, target) must apply the same lex-sort-then-
concat transformation client-side or via a server-provided
helper. A small ergonomic cost; a major correctness payoff.
Seen in¶
- sources/2026-05-29-netflix-high-throughput-graph-abstraction-at-netflix-part-i — canonical wiki disclosure; load-bearing structural invariant of Netflix Graph Abstraction's edge-property storage.