Relationship-shaped questions, answered where the relationships already live.
A native Informix graph extension that traverses the relational data the estate already holds — paths, neighbourhoods, reachability, where-used and the cheapest weighted route — without exporting the graph to a separate database. Verified row for row against the PostgreSQL Apache AGE graph extension.
On the data in place
A bill of materials, an org chart, a network topology, a transaction graph — all of them are edges between rows the estate already stores. The traversal runs inside Informix, against those rows, with no separate graph store to provision, synchronise or secure.
One snapshot, many questions
An ordinary edge table is scanned once into a compact in-memory adjacency structure, keyed by name. Reachability, neighbours, where-used and weighted shortest path then run against that structure, called from ordinary SQL.
Matched against Apache AGE
Neighbours, degree, depth-bounded reachability and connectivity return the identical result to the PostgreSQL Apache AGE openCypher equivalent — asserted equal row for row before any timing is accepted.
Weighted shortest path
The cheapest weighted route runs a Dijkstra traversal with a priority queue — the operation the tested Apache AGE release has no native operator for, and the one a recursive SQL query cannot express economically.
How the graph capability works
The graph is already in your tables
A great deal of enterprise data is a graph in relational form. A bill of materials is a directed graph of assemblies and components; an org chart, a chart of accounts, a network topology, a permission hierarchy and a transaction graph are all edges between rows. The relationships that a graph database would model as its own store already exist in Informix, as foreign keys and link tables.
The recurring questions are traversal questions. Explosion — given a finished product, what is the complete set of components it contains, to any depth. Where-used — given a raw part, which finished products are affected if it is recalled. Reachability — can one node reach another at all, and within how many hops. Cheapest path — the minimum-cost route through a weighted network. Keeping these traversals next to the business data preserves transactional consistency and lets a single statement combine a traversal with ordinary filters on tenant, effective date or status.
How the traversal works
An edge table becomes an in-memory graph; the questions run against it in one pass.
The edge table becomes a graph
A table of source, destination and weight is scanned once with graph_create() into a compact adjacency structure held in shared memory. The relational schema is unchanged; the graph is a projection of rows it already holds. A second snapshot on the reversed edge list answers where-used as a forward traversal.
Visit-once reachability
Reachability and where-used run breadth-first with a visited set, so each node is processed once. Work is bounded by the number of nodes plus edges, not by the number of distinct paths that reach them — the difference that lets a deep, heavily shared hierarchy finish where a recursive query would enumerate paths until it exhausts memory.
The query surface is SQL
Traversals are ordinary functions that return rows — reachable(), neighbors(), degree(), is_reachable(), shortest_path(). Their output joins back to base tables inside a normal SQL statement, under the same access controls and backed up in the same operation as the rest of the estate.
Informix graph and PostgreSQL Apache AGE
| PostgreSQL Apache AGE | Informix graph (ifxtools) | |
|---|---|---|
| Data location | A separate property-graph store, synchronised from the source system | ✓ In the Informix database, on the relational data in place — no second store to keep in sync |
| Model | A native, mutable property graph — nodes and edges carry key/value properties | ✓ An in-memory snapshot of an edge table, rebuilt on demand from the rows already stored |
| Query language | Declarative openCypher (MATCH patterns, variable-length paths) | ✓ SQL function calls whose rows join back to base tables and ordinary filters |
| Neighbours, degree, reachability | Supported natively | ✓ Matched to Apache AGE row for row |
| Weighted shortest path | No native operator in the tested release | ✓ A Dijkstra traversal with a priority queue, answered directly |
| Live updates | A live graph, mutated in Cypher as the data changes | ✓ A read-only snapshot, refreshed when the edge table changes |
| Best fit | Cypher-native applications built around an evolving graph as the system of record | ✓ Repeated traversals over relational data the estate already owns and governs |
Where the traversal is required, and where it is not
Be blunt about it, because it decides whether the extension belongs in a given system. On a small or shallow graph — a few thousand nodes, a few levels, no cycles — a recursive SQL query returns the same answer in single-digit milliseconds and is always current, with nothing to rebuild. Use the recursive query. The extension earns its place only where a recursive query degrades past usefulness as the graph grows, or cannot produce a correct answer at all.
Two thresholds sit on that far side. Feasibility — a deep or heavily shared hierarchy, where a recursive query returns the right answer but its work grows until the query no longer completes; the visit-once traversal keeps it runnable. Capability — a cyclic graph, or weighted shortest path on any non-trivial graph, where a recursive query cannot terminate unbounded and, with a hop limit, is wrong below the optimal path length. Only a settled-set traversal with a priority queue is both correct and bounded. That is the line the extension is built to cross.
What the estate can now answer in place
Relationship-shaped questions on the relational data, without a second system to run.
Bill of materials
Explode a product to every component it contains, to any depth, for costing, procurement and recall scope. Reverse the same graph for where-used — every assembly affected if a part changes or is recalled. A real bill of materials runs twenty to forty levels with heavy part reuse; the visit-once traversal finishes where path enumeration would not.
Network and asset topology
The cheapest weighted route across a distribution network, a road graph or a supply chain, computed with Dijkstra over the lane costs. On a genuine road network of hundreds of thousands of intersections, a point-to-point cheapest route resolves in tens of milliseconds, on the Informix data in place.
Fraud rings and settlement
Inter-account transfer graphs contain cycles, and the fraud question is often literally "is there a path back to the origin?" — a cycle search a recursive query can only do with explicit, costly guards. Minimum-cost settlement and netting paths are weighted shortest path, answered directly.
Organisation and permission hierarchies
Who reports to whom, and who inherits which permission, to any depth — and the reverse traversal, who is affected when a role or an owner changes. Reachability and impact answered on the tables that already hold the hierarchy.
Dependency and impact graphs
Microservice call graphs, build graphs and dependency graphs routinely contain cycles, so reachability and shortest-impact paths have to be cycle-safe. The traversal is settled-set by construction, so a cycle is visited once rather than chased forever.
Entity resolution
Shared-neighbour similarity — Jaccard over neighbour sets, or a weighted cosine over weighted links — surfaces the records that connect to the same counterparties, the raw signal behind resolving duplicate or related entities, computed over the same in-memory snapshot.
Before you put a traversal on the estate.
Does this replace a dedicated graph database like Apache AGE or Neo4j?
No, and it does not try to. Where the workload is a live, evolving property graph queried in openCypher, or where whole-graph analytics over that graph is the primary job, a dedicated graph engine is the right tool and offers a declarative language and a mutable store this extension does not. What this closes is the traversal gap on the relational data the estate already holds — reachability, where-used and weighted shortest path — without standing up and synchronising a separate store. Choose by workload, not by default.
When is a recursive SQL query the better answer?
On a small or shallow graph — a few thousand nodes, a few levels, no cycles — a recursive query returns the identical answer in single-digit milliseconds and is always current, with no snapshot to maintain. Adopt the extension only where a recursive query degrades past usefulness as the graph grows, or cannot produce a correct answer at all: deep or heavily shared hierarchies, cyclic graphs, and weighted shortest path. Do not adopt it to save a few milliseconds on a graph a recursive query already handles.
What actually runs inside the engine?
An in-memory adjacency snapshot of an edge table, and a set of traversal functions over it. graph_create() scans the edge table once into a compact structure in shared memory; reachable(), neighbors(), degree(), is_reachable() and shortest_path() then traverse it. They are ordinary SQL functions, so their rows join back to base tables with normal filters on tenant, effective date or status, in one statement and under the same access controls as everything else.
How current is the answer — is it live?
The snapshot is a point-in-time copy in shared memory; edge-table changes are seen after graph_refresh() rebuilds it. That is the right trade for a graph queried far more often than it changes — a bill of materials, an org chart, a network topology. For a write-heavy graph, either manage the rebuild cadence, or stay with a recursive query, which reads the base table live at the cost of per-query work. The extension does not pretend to be a live mutable graph; a graph database is where that requirement belongs.
Can a traversal be combined with ordinary relational filters?
Yes, and this is the reason to keep it in the engine. Because the functions return rows into a normal SQL statement, a traversal composes with joins, WHERE clauses and aggregates: the reachable components of a product filtered by supplier and effective date, or the assemblies affected by a recalled part restricted to one tenant, in a single query. No export, no round-trip to a second system, no second copy of the access rules to maintain.
How do you know it matches PostgreSQL Apache AGE?
Every result is asserted equal to a textbook traversal reference and to the Apache AGE openCypher equivalent before any timing is accepted. On neighbours, degree, depth-bounded reachability and connectivity the two return the identical result. On weighted shortest path the tested Apache AGE release has no native operator, and the Informix traversal answers it with Dijkstra directly. Parity is verified against the reference engine, not asserted.
Can it also do PageRank, centrality or community detection?
There is an in-engine analytics catalogue that runs over the same snapshot — PageRank, closeness and betweenness centrality, weakly connected components, Louvain and label-propagation communities, single-source distances and shared-neighbour similarity. It is sized for graphs of millions of edges rather than billions, and runs on the data in place. Where whole-graph analytics over a large, evolving graph is the primary workload, a dedicated graph platform remains the right tool; where the analytics are an occasional read over a stable relational graph, they run without a second system.