Back to the blog
HELIX / ENGINEERING LEADERSHIP

Software memory: how to preserve why engineering decisions were made

A durable model for connecting architecture decisions, pull requests, incidents, code, and outcomes so teams stop repeating the same archaeology.

Software MemoryArchitecture DecisionsEngineering GraphsKnowledge Management
A timeline of incidents, decisions, commits, and outcomes flows into a persistent luminous software memory graph.

Software remembers syntax better than meaning.

Git can reconstruct the exact line changed in a commit from five years ago. It cannot tell a new engineer why the team accepted the tradeoff, which incident forced the decision, what alternatives were rejected, or whether the change improved production.

That context usually exists. It is simply scattered across pull requests, chat threads, issue trackers, RFCs, dashboards, and people’s memories.

Software memory is the work of connecting it.

Documentation is necessary but not sufficient

Teams often respond to missing context by writing more documents. The documents help, but they decay because they live beside the work rather than inside its history.

An architecture decision record can say why Redis was introduced. A graph can connect that decision to the incident that motivated it, the pull request that implemented it, the services that still depend on it, the tests that protect the contract, and the latency outcome after deployment.

text
Incident #52
  → LED_TO → RFC-18
  → IMPLEMENTED_BY → PR #284
  → CHANGED → Authentication
  → INTRODUCED → Redis
  → MEASURED_BY → Login latency

The document remains valuable. The relationships make it discoverable at the moment someone changes the affected code.

Memory needs events, entities, and claims

A durable model has three layers:

  1. Events: something happened—a pull request merged, an incident resolved, a decision was accepted, a deployment completed.
  2. Entities: the stable things involved—services, files, teams, dependencies, requirements, environments.
  3. Claims: what the organization believes, plus the evidence and confidence supporting it.

Events update relationships between entities. Claims explain what those relationships mean. Corrections modify the belief without erasing the record.

Capture context where work happens

The easiest memory to preserve is context already produced in a workflow:

  • pull-request descriptions and review discussions;
  • issue links and requirement statements;
  • deployment annotations and rollback reasons;
  • incident timelines, causes, and remediations;
  • architecture decisions and superseding decisions;
  • agent tasks, actions, tests, and verdicts.

Automate ingestion, then make the result easy to correct. Do not ask engineers to maintain a second manual database before the system creates value.

Distinguish history from current truth

Old context is still useful, but it may no longer describe the current architecture.

Use temporal relationships:

text
(service)-[:USED {valid_from, valid_to}]->(dependency)
(team)-[:OWNED {valid_from, valid_to}]->(service)
(decision)-[:SUPERSEDED_BY]->(decision)

Now the graph can answer both “Why was this introduced?” and “Is that reason still current?” It can also show when the answer is uncertain because no later decision was recorded.

Retrieval should reconstruct the story

Keyword search can find an RFC. It cannot reliably assemble the causal path around it.

For a question like “Why do we use Redis?”, resolve Redis as an entity, follow high-value relationships to services, pull requests, decisions, incidents, and metrics, then rank the evidence. The response should sound like an engineer explaining the system:

Redis was introduced through PR #284 after Incident #52 caused database saturation during login spikes. RFC-18 moved session reads out of Postgres. Authentication latency fell from 230ms to 31ms after deployment. Redis is currently used by Authentication, Rate Limiting, and Checkout.

That answer is useful because it connects cause, decision, implementation, outcome, and current use.

Memory should reveal what is missing

A living memory is honest about gaps:

  • a dependency exists, but no decision explains it;
  • a service has an owner, but the relationship is stale;
  • a requirement is stated, but no test verifies it;
  • an incident links to a fix, but no production outcome confirms recovery.

These gaps become work the organization can prioritize. Every closed gap makes future changes easier to reason about.

The compound effect

Teams repeatedly pay for the same rediscovery. A living Engineering Graph turns that cost into an asset.

Each pull request adds change history. Each incident adds failure knowledge. Each correction improves identity and ownership. Each verified agent run adds evidence about autonomous work. Over time, software becomes easier—not harder—to explain.

That is what we mean when we say software should explain itself. The code does not literally speak. The system around it preserves enough connected memory that humans and agents can reconstruct the truth.