Tracks as a Graph: What Neo4j Gives You Out of the Box
Tracks as a Graph: What Neo4j Gives You Out of the Box
Section titled “Tracks as a Graph: What Neo4j Gives You Out of the Box”Suppose you keep a log of what you did — substances, practices, moods, work, sleep — one raw event at a time. In Any Tracker this is the whole contract: just track it. Every log is an append-only fact, and the interesting structure lives between the facts: what tends to follow what, what is a heavier lift than what, which clusters of behavior travel together.
That “between the facts” shape is a graph. So a fair question is: if the log lived in a graph database like Neo4j instead of Postgres, what would we get for free — and is any of it worth a second stateful service?
This is an education piece, not a migration plan. Any Tracker deliberately keeps Neo4j out of the running system (no-neo4j-runtime). By the end you will see why that ban is correct today and not permanent.
Modeling the log as a graph
Section titled “Modeling the log as a graph”The natural mapping:
- Nodes = symbols (
THC 2mg,silence 5m,coffee,doomscroll). Optionally, each logged event is its own node too. - Edges = relations you either observe or ask about:
(:Symbol)-[:NEXT {at, gap}]->(:Symbol)— a transition: B was tracked right after A. This is the Markov structure we already compute in SQL with alag()window.(:Symbol)-[:EASIER_THAN {confidence}]->(:Symbol)— an ordinal relation, learned from pairwise probes (“what’s usually easier, A or B?”).
Once the data is edges, a graph database earns its keep on three fronts: traversal, pathfinding, and a graph-algorithm library. Plus visualization as a bonus.
1. Traversal: variable-length patterns in one line
Section titled “1. Traversal: variable-length patterns in one line”The thing Cypher (Neo4j’s query language) does that SQL fights you on is the variable-length path. “What tends to happen within three steps after THC?” is a recursive question. In SQL it is a recursive CTE you have to hand-roll and reason about carefully. In Cypher:
MATCH (a:Symbol {token: 'THC 2mg'})-[:NEXT*1..3]->(b:Symbol)RETURN b.token, count(*) AS reachableORDER BY reachable DESCThe *1..3 is native. Chains, loops, “does A ever lead back to A”, motifs like “A then B then not-C” — these read almost like the sentence you would say out loud. When your questions are about sequences and reachability, this is a real ergonomic win.
2. Pathfinding: the route between two states
Section titled “2. Pathfinding: the route between two states”This is the one that actually touches Any Tracker’s deepest ambition. The product’s telos is a transition operator: help someone move from a current stable pattern to a target one, along a route they can actually walk. That is literally a pathfinding problem on the behavior topology.
Neo4j ships shortest-path and weighted-path algorithms out of the box:
MATCH (from:Symbol {token: 'doomscroll'}), (to:Symbol {token: 'silence 5m'})CALL apoc.algo.dijkstra(from, to, 'PRECEDES>', 'cost') YIELD path, weightRETURN path, weightWeight the edges by effort (the inverse of the ordinal ease you calibrated) and the shortest path becomes the least-resistance route from where you are to where you want to be — deepen the target basin, one reachable step at a time, never asking for a leap you can’t afford. Dijkstra, A*, and Yen’s k-shortest-paths are all built in. You do not implement any of them.
3. The Graph Data Science library: an algorithm suite for free
Section titled “3. The Graph Data Science library: an algorithm suite for free”Neo4j’s GDS plugin is where “out of the box” gets generous. Installed, not written:
- Centrality — PageRank, betweenness, degree. Which symbols are the hubs and gateways of your behavior? A high-betweenness symbol is a bridge: the thing you pass through to get between routines. Worth knowing if you want to nudge at a chokepoint.
- Community detection — Louvain, Label Propagation. Which symbols cluster into routines? Your “wind-down evening”, your “deep-work morning” — surfaced as communities, not hand-labeled.
- Similarity / kNN — which symbols play structurally similar roles even if you never do them together.
- Link prediction — from common neighbors and adjacency, guess the edges that don’t exist yet but probably should: the next transition you haven’t logged.
Each of these is a one-call procedure. Writing correct, performant PageRank or Louvain yourself is a project; here it is a line of Cypher.
4. Visualization, thrown in
Section titled “4. Visualization, thrown in”Neo4j Browser and Bloom render the graph immediately — no frontend to build. For an N=1 research instrument, being able to look at your own topology and watch it deform over weeks is not nothing. The vision already leans on a “stable, glanceable map” as the canonical feedback artifact; a graph view is a different, complementary lens on the same latent structure.
The honest counter: what Neo4j does not give you
Section titled “The honest counter: what Neo4j does not give you”Now the part that keeps the ban standing.
It does not give you the edge. Any Tracker’s actual innovations are statistical, not graph-topological:
- The honest sign (“better / about the same / worse than a fair forecast of yourself”) is a state-space innovation — a forecast residual with a deadband. No graph algorithm produces it.
- The ordinal topology itself is a Davidson dynamic Bradley–Terry model: latent per-symbol Gaussian beliefs updated from three-way (
> = <) answers, with random-walk drift for non-stationarity. Neo4j can store the resultingEASIER_THANedges, but it does not fit the model. The inference — the thing that is hard and valuable — lives in application code either way.
So the graph database would hold the output of the interesting math, not produce it. Centrality and community detection over that graph are genuinely cute, but “cute” is not the value proposition. The value proposition is a shame-free sign and a well-timed nudge.
Postgres already covers the queries we actually run. At N=1, data volume is tiny. Transitions are a lag() window we already ship. Multi-hop reachability is a recursive CTE — uglier than Cypher, but correct and instant at this scale. We are not query-bound; we are insight-bound.
And the cost is a whole second source of truth. Another stateful service to deploy, back up, monitor, and keep consistent with Postgres. For a tool whose only real currency is honesty of the log, splitting that log across two databases buys graph ergonomics at the price of a consistency problem. That trade is bad while the graph questions are still hypotheses.
When the ban should lift
Section titled “When the ban should lift”Not never — not yet. Neo4j earns its place the day two things become live product features rather than daydreams:
- Transition pathfinding — when we actually plan routes across the attractor topology (Layer 3), and shortest-weighted-path over a large, dense symbol graph becomes a hot path.
- Routine discovery — when community detection over the behavior graph drives real recommendations (“this belongs to your wind-down cluster”), not just a pretty picture.
Until then, the rule holds: graph database as complexity ahead of value. The out-of-the-box goodies are real — traversal, pathfinding, GDS, visualization — but you adopt a graph database when your questions are graph-shaped and heavy, not because your data can be drawn as dots and lines. Almost any data can.
The one-line takeaway
Section titled “The one-line takeaway”Neo4j gives you traversal, pathfinding, a centrality/community/link-prediction algorithm suite, and instant visualization — for free. It does not give you Any Tracker’s edge, which is latent-variable statistics (the honest sign, the Davidson ordinal model) that run in application code no matter where the graph is stored. Adopt it when route-planning on the attractor topology is a shipping feature, and not one day sooner.