Feb 15, 2026 · 11766 words · 56 min read

The Source of Truth#

A new service needed to go live by end of week. The change was straightforward: a new VLAN, a new subnet, updated firewall rules, and a new BGP community on the edge routers. The network engineer knew exactly what to do. What followed was four days of coordination across five systems: the IPAM tool to reserve the subnet, a Service catalog to register the service, the firewall management platform to push the new policy, the router configuration system for the BGP community, and the monitoring platform to add the new thresholds. Each system had its own interface, its own data model, its own approval workflow. And because there was no shared reference, the engineer had to carry the context manually: copying values from one system to the next, hoping nothing drifted between steps.

Six months later, the service was decommissioned. The VLAN got removed. The subnet was freed. But the firewall rule stayed. Nobody remembered it was linked to that service. The BGP community lingered on two edge routers. The monitoring threshold kept firing low-priority alerts that the NOC learned to ignore. Over time, the network accumulated layers of orphaned configuration: remnants of changes that were never fully tracked, never fully reversed, never connected to a shared record of intent.

This is what running a network without a source of truth actually looks like. Not a single dramatic failure, but a slow accumulation of inconsistency, where every change requires updating multiple disconnected systems, and where nothing keeps track of what belongs together.

Nothing in that story is a modeling failure. Each of those five systems held correct data about its own domain: the subnet was right in the IPAM, the policy was right in the firewall manager, the threshold was right in the monitoring platform. What was missing was everything around the data. One place that joined the five. A record of which service each value belonged to. And anything at all that noticed when the service went away and its leftovers did not.

That is this chapter. Chapter 4 set out the five goals of the Source of Truth and then settled the data itself: what the intent holds, how it layers, and what makes a value valid. What remains of those goals is machinery, and three functionalities deliver it:

  • Data Persistence stores the intent, answers questions that cross several objects, keeps its complete history, and records where each value came from, so you can still say what was true last Tuesday and which system decided it.
  • Data Consumption serves the data to the people and systems that need it, each at the shape it needs, and governs who may read, who may write, and who may change the schema.
  • Data Federation joins the systems that already hold authoritative data, on a single principle: exactly one authority per piece of data.

Each one answers a part of the story. Federation is what that engineer was doing by hand for four days. Consumption is why there was no single interface to ask in the first place. The lineage metadata inside persistence is what would have recorded that the firewall rule belonged to that service, and the reconciliation process later in this chapter is what would have found the rule once the service was gone.

They also stack, on the schema from Chapter 4 and on each other. Persistence is pointless if the data was never valid. Consumption serves whatever persistence holds. Federation decides which values persistence is entitled to accept at all. This chapter takes them in that order, then covers the operational realities that decide whether the SoT stays credible after go-live, and closes on the same campus network as Chapter 4.

A word on boundaries, because three of them cause confusion and two of them are with chapters either side of this one.

What’s in scope

  • Where the intent lives, how concurrent changes stay consistent, and how to reconstruct what was true at any past moment
  • How every consumer reaches the data, at the shape that consumer needs, under access control
  • How the systems that already own authoritative data are joined to this one, and who wins when they disagree
  • The operational realities that decide whether the SoT stays credible after go-live

What’s out of scope

  • What the intent contains and what makes a value valid, which is the data itself (Chapter 4, where Figure 4.3 maps all five Source of Truth goals across both chapters)
  • Rendering intent into device configuration, also Chapter 4: this chapter stores and serves the record, it does not turn it into commands
  • The automation platform’s outward-facing API (Chapter 9). The SoT’s API answers “what should this device look like” for the systems inside the platform; the Presentation layer’s API answers “deploy this service” for consumers outside it. Both are APIs, and they have different audiences and different contracts
  • How the Executor consumes what this block serves (Chapter 6)

Start with where the intent lives.

Functionalities#

Data Persistence#

Your network intent changes constantly. Devices are added, configs updated, services moved, policies tweaked. Data Persistence is where that intent actually lives, and it settles four questions you will care about later: whether you can get an answer back out of it, whether simultaneous changes stay consistent, whether you can reconstruct what was true last Tuesday, and whether you can say where a given value came from.

Those are four distinct jobs, and this section takes them in order:

  • Queryability: the data comes back in the shape your questions need, including the questions that cross several relationships. Persistence decides which answers are cheap to get; Data Consumption decides how they reach a consumer.
  • Transactional integrity: several writers (people, controllers, workflows, agents) change shared data without corrupting it or quietly overwriting each other.
  • Versioning: every change is recorded, so intent can be traced, compared, and rolled back.
  • Lineage: metadata stored next to the intent records who owns each value and where it came from. This is data about your data, and it is what makes federation and access control workable.

Implementations range from YAML files in a Git repository to a purpose-built graph database, and they differ enormously in what they hand you for free. Start with where the data sits.

Choosing how to store model data has profound implications for consistency, performance, and evolution. These implications become critical as your network grows from hundreds to hundreds of thousands of managed objects. Figure 5.1 maps common requirements to the store that fits each one, and the list below walks through the four options.

Database decision table

Figure 5.1: Requirements mapped to the data store that fits each one.
  • Files in Git (e.g., YAML or JavaScript Object Notation (JSON) documents, sometimes CSV): The lightest option, and the only one where history, branching, diffing, and review come for free because the storage engine was built for exactly that. It suits small or slow-moving estates, and it is how many teams start. The limits arrive with scale: no referential integrity, no indexed queries, and every consumer parses the whole file to answer a question about one device.

  • Relational Databases (e.g., MySQL, PostgreSQL): This is the safe bet for most teams because it’s a proven technology. They enforce schema consistency, provide Atomicity, Consistency, Isolation, Durability (ACID) transactions, and most engineers on your team already know SQL. They excel at representing normalized hierarchies (VLANs containing interfaces) and preventing data anomalies. The downside: schema changes hurt at scale, and performance tanks with deep joins across millions of rows.

  • Document Databases (e.g., MongoDB, CouchDB): Great if you need schema flexibility and horizontal scalability. Documents naturally model nested structures (a device with all its configs and metadata as one blob). But here’s the catch: you’re largely responsible for consistency across documents, and complex queries get expensive fast. Unless you have a specific reason to go document-based, stick with relational.

  • Graph Databases (e.g., Neo4j): These are genuinely better when relationships matter more than objects: “which VLANs does this interface connect to? What devices route between these two locations?” They traverse relationships of arbitrary depth efficiently. But unless you’re doing complex topology queries constantly, you’re choosing the exotic option. Your ops team doesn’t know it, the tooling is less mature, and write performance lags for simple updates. Graph databases solve real problems, but make sure you actually have those problems first.

Database selection is one of the key differentiators among products in this space. For example, NetBox and Nautobot use relational databases, while Infrahub uses a graph database, as you can see in the Solutions Landscape section.

Most production Source of Truth systems use polyglot persistence: a relational database for authoritative intent and relationships, document storage or Git for flexibility and caching, and graph capabilities for topology analysis.

In Chapter 12, we will cover more insight on how decisions like this impact performance.

Querying Connected Data#

The storage choice looks like a write-path decision. It is mostly a read-path decision, and the queries that settle it are the ones that cross relationships.

Look at what automation and engineers actually ask of a network model:

  • Which devices are affected if circuit C-2271 goes down? Circuit, to its terminations, to interfaces, to devices, to sites. Four hops.
  • Where is 192.0.2.1 used? One address, referenced from an interface, a BGP neighbor, a tunnel endpoint, and a service. One hop, four directions.
  • Which prefixes are live on the access switches in Building B that run a given platform? Site, to devices filtered by role and platform, to interfaces, to prefixes. Three hops with a filter at each level.
  • What else rides the uplink this service crosses? Service, to its interfaces, to the uplink, back out to every other service that touches it. Unknown depth, because the answer depends on the topology.

None of those is exotic. The first one is impact analysis before a maintenance window, the second is what you ask before reusing an address, and the last is what an engineer wants before draining a link. A SoT that cannot answer them sends people back to Secure Shell (SSH) sessions for the answer, which is where this chapter started.

What each store charges you for those questions is the real difference between them:

  • Relational stores answer them declaratively. A four-table join is a normal day: you write it once, the query planner works out how to run it, and indexes keep it quick. The limit is depth you cannot predict. “Every device downstream of this one” becomes a recursive query, which SQL can express but nobody enjoys writing.
  • Graph stores make exactly that case native. Variable-depth traversal is the primitive, so impact analysis reads almost like the question. You pay elsewhere: fewer engineers can write the queries, and a plain attribute filter is no faster than it would have been in a relational store.
  • Document stores answer anything inside one document immediately, and anything across documents in your application code. The join becomes a loop: fetch the devices, then fetch each device’s interfaces, then fetch each interface’s prefix. That is the N+1 query pattern, and it has two costs. Every consumer reimplements the join, and the latency is the fan-out rather than the query.
  • Files in Git have no index at all. Every question is a scan of the tree, and a relational question means loading the tree into memory first. Workable at 200 devices, a losing game at 20,000.

Two caveats matter more than the comparison itself.

First, the backend’s capability is capped by the interface in front of it. Most consumers never touch the store; they go through the SoT’s own Application Programming Interface (API), and an API that returns one object type per call hands you the N+1 problem even with a relational database behind it. That is why Data Consumption treats read flexibility as an interface decision and not only a storage one.

Second, when a question stays expensive whatever you do, precompute the answer. That is the projection in Context-Aware Data Modeling, and it buys speed with freshness.

So before choosing a store, write down the ten questions your automation and your engineers will ask most often, and count the hops in each one. If nearly all of them start from an object whose id you already hold and stop one hop later, the choice barely matters. If several are “what else is affected by this” and the depth is not fixed, that is a requirement, not a preference: no amount of schema work later adds a capability the store does not have.

One of the key challenges to solve in the persistence layer is conflict handling.

Transactional Data#

Assume more than one writer. A single-writer SoT is a comfortable fiction that breaks in the first week: an engineer edits a device in the UI while a reconciliation job syncs the same device from IPAM, a controller updates interface state, and an agent proposes a bulk change across the whole site. All four can touch the same record inside the same second.

The architectural requirement is blunt: multiple writers must be able to operate on shared data without silently overwriting each other’s intent. Silently is the load-bearing word. A conflict that surfaces as an error is an inconvenience. A conflict that resolves itself by discarding somebody’s change is a future outage that nobody will be able to explain.

There are different mechanisms that get you there:

  • Optimistic concurrency: every record carries a version. You submit the version you read; if it has moved on, your write is rejected and you retry against current state. Cheap, and it fails loudly, which is exactly what you want here.
  • Explicit conflict resolution: when a merge genuinely cannot be decided automatically, park it and ask a human. Git branch merges are the usual case.
  • Transactions: group related writes so they commit or fail together, covered next.

Pessimistic locking is the obvious remaining option, and at this layer it is usually a trap. A held lock blocks the very automation you are trying to enable, and a lock somebody forgot to release blocks it indefinitely.

This section covers conflict management within a single data source. Conflicts across data sources belong to Data Federation, where you solve them by declaring which writer owns which attribute. The IPAM owns the address, the central SoT owns the interface it is assigned to, and neither can clobber the other even when both write the same object.

Transactional guarantees ensure data consistency when multiple related changes must succeed or fail together. These are the four ACID properties:

  • Atomicity: A transaction is all-or-nothing. If any part of it fails, the whole thing rolls back as though it never happened. You never land in a half-applied state where the VLAN exists but the prefix it needs does not.
  • Consistency: A transaction moves the store from one valid state to another, respecting every constraint, relationship, and type rule you defined. It will not leave data that violates those rules, even when the transaction itself succeeds.
  • Isolation: Concurrent transactions do not interfere, and ideally each behaves as though it ran alone. Databases offer a range of isolation levels that trade strictness for throughput, and the weaker ones let one workflow allocate a prefix that another is halfway through claiming. Chapter 12 covers consistency models and where each level is safe.
  • Durability: Once a transaction commits, its changes survive a crash, a power loss, or a restart, usually because they reach a write-ahead log before the commit is acknowledged.

The alternative model is BASE (Basically Available, Soft state, Eventually consistent), which relaxes those guarantees in exchange for availability and horizontal scale. That is the right trade for a telemetry pipeline swallowing millions of points a second. It is usually the wrong trade for intent. Consistency is the entire point of a source of truth, and BASE does not remove the need for it: it moves the work to every client, each of which now has to reconcile what it read against what may have changed since. Prefer ACID for intent, and leave BASE to the observability data in Chapter 7.

In Chapter 12, we will cover more about how these requirements impact reliable systems.

Versioned Data#

Your network will change, and the change starts with your data: a new circuit, an IP address reassignment, a decommissioned site. The data persistence block should offer two capabilities:

  • An audit trail, so you can see when the data changed, who changed it, and why.
  • A timestamped snapshot of the data at any point, which doubles as a rollback safeguard.

An audit trail records every change immutably, building a complete history. It can take different forms. A structured change log records the before and after of each field, along with who asked for it and why:

Change Event:
  timestamp: 2026-02-07T14:32:15Z
  user: engineer@example.net
  action: UPDATE
  resource_type: vlan
  resource_id: vlan-100
  changes:
    description: "Customer VLAN" → "Production Customer VLAN"
    assigned_sites: [site-a, site-b] → [site-a, site-b, site-c]
  reason: "Adding new office location"
  request_id: req-12345
Listing 5.1: A change-log entry recording a VLAN update, its author, and its reason.

A Git commit does the same job with different machinery, and gets branching and diffing along with it:

commit 0c0ad51152f9b3be307802badb15eca8d121c576 (HEAD -> new-site, origin/new-site)
Author: Engineer <engineer@example.net>
Date:   Sat Feb 7 09:43:59 2026 +0100

    Adding a new site: BCN01

diff --git a/sites.yaml b/sites.yaml
index ae18c87..dabf6c5 100644
--- a/sites.yaml
+++ b/sites.yaml
@@ -219,3 +219,7 @@ sites:
   MAD01:
     region: emea
     status: active
+  BCN01:
+    region: emea
+    status: planned
+    prefix: 192.0.2.0/24
Listing 5.2: The same job done by a Git commit.

Whichever form it takes, the value of the log is in the questions it can answer, and each one maps to something you will need on a bad day:

  • Time travel: what was the network intent on 7 February? This is what lets you rebuild a site to the state it had before a migration, and what lets an auditor see the intent that was in force during an incident rather than the intent you have now.
  • Accountability: who made this change, and why? The why matters more than the who. A record that says an engineer widened a prefix tells you little; one that carries the change request behind it tells you whether the change was wrong or merely surprising.
  • Traceability: which deployed configuration corresponds to this intent? This is the link between a device that is behaving strangely and the decision that made it that way, and without it every investigation starts from scratch.
  • Diff and comparison: what changed between version Y and version Z? This is the basis of review before a change and of blast-radius analysis after one, and it is what turns “something changed last night” into a list of the 14 objects that did.

A key property of an audit trail is immutability: nobody, not even administrators, can edit a historical record. This prevents cover-ups and keeps the trail trustworthy. Immutable is not the same as permanent, and the difference is what makes retention possible: a record may never be rewritten, but it may expire under a policy you published in advance. Deleting on a published schedule is itself auditable. Editing in place is not.

Audit trails grow forever (deleting data still creates an entry), so plan that policy explicitly, balancing compliance against cost. For example:

  • Full fidelity for 2 years: every change to every field.
  • From 2 to 7 years, keep the first and last value of each field and drop the steps in between, so a VLAN that changed 10 times keeps 2 entries.
  • Move anything older than 1 year to cold storage, which is a separate decision from fidelity: cheap to hold, slow to read.

Related to data change events, event sourcing patterns (storing all changes as events for full data recreation) are powerful but they are less common in network infrastructure management. This is because network intent is highly stateful. The current data is more important than the sequence of changes that led to it. Additionally, network changes often involve external state (device configurations, IP allocations in external systems) that cannot be fully recreated from events alone. However, event sourcing can be valuable for specific use cases like audit compliance or forensic analysis.

These audit trail properties enable a particularly useful capability: moving through time in both directions. Modern Source of Truth systems borrow heavily from software version control patterns here. These capabilities enable safe parallel work, experimental changes, and rapid recovery from mistakes.

Branching for Parallel Work Streams

Any organization with more than one engineer or AI agent working in parallel needs a way to work without blocking others.

Learning from software development, branching mechanisms enable parallel work streams. Each entity can work on parallel data tracks and finally merge them with the “main” track when ready. This merge is an opportunity to resolve any inconsistencies that may have been introduced.

For example, using Git as the version control mechanism, this could look like the following workflow:

main branch (production intent)
  │
  ├─── feature/add-dallas-office (Engineer A)
  │     • Creates site DAL-01
  │     • Allocates VLANs 2100-2110
  │     • Defines 5 new devices
  │     • Adds an uplink on device-core-01
  │
  └─── feature/upgrade-ntp-servers (Engineer B)
        • Changes NTP config for all devices
        • Updates 3,000 device records
Listing 5.3: An example Git branching workflow.

When both branches merge back to main:

  • No conflict: Different objects modified → auto-merge
  • Conflict detected: both branches wrote device-core-01, A the uplink and B the NTP server. Whether that is a real conflict depends on your merge granularity: a field-level merge takes both, an object-level merge stops and asks
  • Validation: Merged result must pass all enforcement rules before commit

Implementing this branching mechanism into traditional databases is an important problem in its own right. For example, NetBox and Nautobot, which rely on relational databases, have taken different approaches: NetBox uses database copies for branching, while Nautobot leverages Dolt (a SQL database with built-in Git-like Versioning). Infrahub, designed from the ground up with Git-like branching in mind, implemented this using a graph database with native branching capabilities built-in.

Rollback and Recovery

Mistakes happen. Data rollback must be fast and reliable. Note that this is the rollback of the technical layer data itself, not of the network configuration rendered from it.

To support data rollback, there are three approaches, and most production systems end up at the third:

ApproachHow It WorksStorage OverheadRecovery SpeedComplexity
SnapshotsPeriodic full copies of entire datasetHigh (full copy per snapshot)Fast (direct restore)Low
Event SourcingRecord all changes as events, replay to reconstruct stateLow (only deltas stored)Slower (must replay events)High, and see the caveat above: intent that depends on external state cannot be fully rebuilt from events alone
HybridSnapshots every N hours + event log between snapshotsMediumFast to snapshot, then replay eventsMedium
Table 5.1: Approaches to supporting data rollback, comparing storage overhead, recovery speed, and complexity.

Rollback may be triggered in two ways:

  • Manual: Operator recognizes problem, initiates rollback
  • Automated: the Orchestrator decides to roll back when Observability reports a problem after deployment:
    • Error rates rise
    • Post-deployment validation fails (“500 devices unreachable after change”)
    • A business impact threshold is exceeded (“customer SLA violations > 10”)

The combination of branching (parallel work without conflicts) and rollback (rapid recovery from mistakes) provides the temporal flexibility that demanding network automation requires.

The capacity to branch data, rather than activating a change directly, is what enables change approval workflows. Once data changes are proposed, they may require human approval workflows before becoming active. Data typically flows through several stages before being considered final, similar to continuous integration pipelines.

Three chapters meet at this point, and it helps to know which owns what. This one owns the data mechanism: branch, propose, check, approve, merge. Chapter 11 owns the pipeline that runs those checks and the release gates that act on the result, so a proposal that fails simulation is not promotable regardless of who tries. Chapter 13 owns the governance: which changes a guardrail may approve on its own, and which still need a person.

Data Approval Workflow

Figure 5.2: A data change-approval workflow.

An example data change workflow might look like:

  1. Operator proposes change: “Add 50 new branch devices” and the change enters STAGING: (no effect on network yet, can be previewed, tested, dry-run)

  2. Automated checks run (Continuous Integration):

    • Validation: Does it pass schema and constraints?
    • Simulation: Does it break routing, MPLS, etc.?
    • Compliance: Does it violate security policies?
    • Report: all checks passed
  3. Human review:

  4. Data persisted: once approved, the data gets persisted, and it may trigger the Orchestrator to eventually deploy the related changes to the network (a common trigger for automated execution workflows)

Not every change should take that path, though, and deciding which ones do is a governance question rather than a persistence one. The short version: build guardrails that let the routine majority through automatically and reserve human review for what falls outside them, because a CAB that meets weekly to approve VLAN additions will outlive your automation program. Chapter 13 covers change governance, approval gates, and where to draw those lines.

Another important functionality, one that stays invisible to many people until it is missing, is data lineage.

Data Lineage#

Next to the intent itself sits a second, much smaller body of data that is not intent at all: data about the data (usually known as metadata). Who owns this record. Which system it came from. When it was last synced. Whether anybody has touched it since.

This is lineage, and teams tend to discover they need it late, usually just after an incident where nobody could say where a value came from. It is worth designing in from the start, because two other functionalities lean on it:

  • Federation needs to know, value by value, which system is authoritative and whether the local copy is just a copy. A prefix that arrived from IPAM two hours ago and a prefix an engineer typed in by hand are different things, and only metadata tells them apart.
  • Access control and auditing need ownership to be a property of the data rather than a convention in somebody’s head.

In practice it is a handful of attributes hanging off every object. For data this SoT authors itself:

locations:
  - name: BCN01
    prefix: 192.0.2.0/24
    _metadata:
      owner: "network-eng@example.net"
      source: null                      # authored here
      last_modified: "2026-03-14T09:21:00Z"
Listing 5.4: Lineage metadata on locally owned data.

And for a value this SoT holds but does not own:

primary_ip:
  address: 192.0.2.2
  mask: 26
  _metadata:
    owner: null                         # nobody here owns it
    source: "external-ipam"             # this is a copy
    last_synced: "2026-03-14T07:55:00Z"
Listing 5.5: Lineage metadata on federated data.

The source and last_synced pair is what lets a consumer make a judgment call. Data synced four minutes ago is usable. Data synced last quarter needs a refresh before you build a change on top of it, and without the timestamp there is no way to tell the two apart.

This is also what makes the governance matrix in Data Federation enforceable rather than aspirational. That matrix states which system is authoritative per data domain; the lineage metadata is what records that decision on each individual record, so a consumer can check it without having to know the policy by heart.

Push the idea further and you get data provenance, where traceability reaches individual parameters instead of whole records. That lets you ask who or what last set this one field, the way git blame answers the question for a line of code, and it is the difference between “this record changed on Tuesday” and “this is the automation run that put the wrong address here”.

After the data is persisted, it’s time to start using it.

Data Consumption#

Data locked away in a database is useless. Data Consumption is how people and systems actually get their hands on the data. Make it easy, and you get buy-in. Make it hard, and people will work around it.

Reads and writes are not symmetric, and designing as though they were is a common mistake. Writes are comparatively rare, and they want every guarantee from the previous section: validation, transactions, conflict detection. Reads happen constantly, from every workflow, dashboard, and agent you run, and they want speed and expressiveness, which pull against each other. GraphQL lets a client ask for exactly the fields it needs, but the server is what executes that query, so the most flexible interface can become the slowest one under load. Decide per use case which side you are optimizing for, rather than picking one interface and hoping it covers everything.

Users reach this block through the Presentation layer, since the products implementing it almost always embed some UI. In general terms, though, the block exposes its data through APIs. Several options exist; these are the most popular today:

InterfaceRequest PatternUse CaseCharacteristics
Representational State Transfer (REST)Hypertext Transfer Protocol (HTTP) verbs (GET, POST, PATCH, DELETE) on resource URLsGeneral-purpose CRUDSimple, widely understood, and stateless, but can require many requests, and versioning gets awkward
GraphQLSingle endpoint, client specifies exact fields neededComplex multi-resource queriesFlexible and client-driven, so no over-fetching, at the cost of a more complex server and the N+1 query risk
gRPCProtobuf-based RPC over HTTP/2High-performance, low-latencyBinary encoding and HTTP/2 multiplexing make it several times faster than JSON over HTTP/1.1 on chatty workloads, though the margin depends heavily on payload shape, but a steeper learning curve and limited browser support
WebhooksServer pushes changes to registered endpointsReactive automation, near-real-time syncAsynchronous and decoupled, with no polling overhead, but delivery is unreliable and retries and security need handling
Table 5.2: A comparison of API styles.

Most SoTs end up offering several of these at once, and that is fine. What matters for this chapter is the shape of the choice, not the detail of the interface: Chapter 9 covers API design, documentation, and client surfaces properly.

Every one of those is a pull interface except the last, and that exception generalizes. Alongside querying synchronously, a consumer can subscribe to change and be told when intent moves, through a webhook or a message bus. It works in both directions: downstream systems subscribe so they can act the moment a VLAN is approved rather than discovering it on the next poll, and the SoT subscribes to upstream systems so a prefix allocated in IPAM arrives here without waiting for a scheduled job. The delivery mechanics and latency trade-offs belong to federation, and Data Federation covers them.

In addition to traditional API styles, emerging interaction models such as the Model Context Protocol (MCP) enable AI agents to interact with systems in a structured, tool-oriented manner. Unlike REST or gRPC, which define transport and request semantics, MCP focuses on safe capability discovery, contextual data retrieval, and controlled action execution for agent-driven workflows. This pattern is particularly relevant in AI-assisted operations and observability use cases, where automated reasoning systems need structured access to telemetry, configuration, and remediation tools. While still evolving, MCP represents a shift from resource-centric APIs toward agent-oriented interaction models.

One critical point: do authentication and authorization at the API layer, not downstream. This prevents security holes and makes auditing work properly. More about security implications in Chapter 13.

This Intent data defines how the network runs, so changing it is equivalent to changing the network. Apply least privilege exactly as you would to device access: nobody gets more reach than their role needs.

There are three distinct permissions here, and systems routinely collapse the third into the second:

  1. Who can read which data. Not every consumer should see every field; credentials, security zones, and cost centers each have a different audience. This is the enforcement half of the per-persona views from Data in Scope, and Context-Aware Data Modeling below covers how to shape them.

  2. Who can modify which data. Scoped by object type, by attribute, and usually by site or tenant too. The field-level ownership from Transactional Data is the federated case of this same rule.

  3. Who can change the schema. This is a separate and far more dangerous permission, and the one most often granted by accident. Editing a VLAN record affects a VLAN. Removing a required field, loosening a constraint, or dropping a relationship affects every record of that type and every consumer that trusted the contract. Somebody who can relax validation can introduce bad data everywhere at once without ever writing a bad value themselves. Treat schema changes like code changes: distinct permission, review, staged rollout.

Pair all three with a record of what actually happened. Authorization states what is permitted; the change history from Data Persistence states what was done, and the lineage metadata states where each value came from. Without the last two, the first is unauditable.

Once APIs are designed and secured, two operational concerns follow, and both have fuller homes later in the book.

  • Evolution: Automation workflows outlive the API versions they were written against, so breaking changes need announcing months ahead. My one opinion worth keeping here: put the version in the URL, not a header. Header versioning reads better in documentation, but at 3am you want /v1/ visible in a log line rather than buried in request headers. Chapter 9 covers interface versioning and stability in full.

  • Scale: Reading and writing one object at a time stops working somewhere around the thousandth device. Bulk endpoints are the usual answer, and they carry an SoT-specific cost: to go fast they relax exactly the guarantees Data Structure spent its time establishing, skipping expensive cross-object checks and making per-object error reporting harder. That is the synchronous-versus-deferred validation trade-off again, surfacing on the API. The rest of the toolkit (pagination, filtering, caching, read replicas, rate limiting) is general platform work rather than SoT design; Chapter 12 covers SoT retrieval at scale and Chapter 9 covers rate limiting and the interface side.

One newer trend that makes data consumption more effective is shaping it to different contexts.

Context-Aware Data Modeling#

Different people need different things. Network engineers want to search and find data, edit specific fields with validation feedback, see relationships. Automation workflows need APIs, transactions, and webhooks. Operations teams want task-focused views and audit trails. Business wants reports without technical detail. External systems need to sync data both directions.

Notice that the user interface of the Data Consumption block belongs to the Presentation layer. We will cover more about this in Chapter 9.

The data representation has to adapt to each consumer context. For example, not every device detail has to be exposed to every persona. Context-aware customization makes data consumption more efficient and effective without changing the persisted data.

Keeping in mind the different network data families you need (hardware details, IP addresses, and so on), different consumers need different views of that data. The next table shows a typical classification of contexts and consumers for device-related data.

Consumer and ContextData RepresentationKey Attributes
Network Engineer
Troubleshooting connectivity
Network-centric viewInterfaces, IP addresses, BGP peers, routes, VLANs, uplink status
Finance Team
Cost allocation
Business-centric viewCost center, depreciation schedule, warranty status, purchase date, vendor
Security Team
Compliance audit
Security-centric viewCompliance zone, access policies, last security scan, patch level, open vulnerabilities
Automation Workflow
Configuration deployment
Execution-centric viewManagement IP, credentials reference, device platform, config template name
Service Catalog
Customer impact analysis
Service-centric viewCustomers served, services hosted, SLA tier, redundancy group
Table 5.3: How the same data adapts to context.

There are different ways to achieve this contextualization. Using device-related data as the example, let’s look at the options:

View-based transformations compute the shape on demand, per request, over one record or a filtered set of one type. The server holds one representation and reshapes it as it answers. The API query names the context it wants:

GET /api/devices/router-core-01?view=network-engineer
→ Returns: {interfaces: [...], bgp_peers: [...], vlans: [...]}

GET /api/devices/router-core-01?view=finance
→ Returns: {cost_center: "...", warranty_expiry: "...", purchase_cost: ...}
Listing 5.6: One device, two view-based transformations of the same record.

Projection layers go the other way. The shape is computed ahead of the request and stored, it spans many records and usually several object types, and it has to be maintained as the underlying data changes. A topology graph of every device and cable, a service dependency tree, a compliance matrix per zone: each one answers a question that would otherwise mean correlating thousands of records at read time.

It is the database distinction between a view and a materialized view, and it carries the same consequences. A projection answers fast and can be stale, so it needs an invalidation rule: recompute on write, recompute on a schedule, or accept a known staleness window and publish it. That makes a projection a data decision rather than an interface one, which is why it sits here rather than in the Presentation layer.

The other two ways to shape data are interface concerns, and Chapter 9 owns both: letting consumers select fields themselves with GraphQL, which that chapter demonstrates with the same two contexts used above, and exposing a domain-specific query language per audience, which Large Language Model (LLM)-backed interfaces have made far cheaper to build than it used to be.

Whichever mechanism you pick, the cost is the same and it is worth naming: every view is a thing to define, test, document, and keep consistent with the others, and consumers have to discover which views exist before they can use them. A projection adds one more, because a stored derivative of your data is a second thing that can be wrong.

Context-aware modeling is the bridge between data structure optimization (how we store data efficiently) and consumption optimization (how consumers access data naturally). It recognizes that the Source of Truth serves many masters, each with their own perspective on what “truth” means for their work.

AI helps on the read path too, for the same reason it helps on the write path: the model is large and nobody holds all of it in their head. Three patterns recur. Contextual suggestions complete a device name from the ones you have edited in that location, or propose service parameters from the service type, cutting input errors without adding validation friction. Anomaly warnings question an operation that looks unlike its predecessors, so a bulk VLAN reassignment that usually touches ten devices and is about to touch four hundred earns a confirmation step. Natural language queries let an operator ask “which devices in Building B have no monitoring tag” and get a structured query run on their behalf, which is useful for investigation and no substitute for a structured interface in automation.

All three rest on the same foundation as the write-path techniques: historical operation data, and a schema well enough modelled for the AI to reason over. Schema and Constraint Enforcement covers that side.

Finally, the last functionality to cover is how to coordinate multiple systems into one consistent Intent block.

Data Federation#

A man with a watch knows what time it is. A man with two watches is never sure.

Segal’s law

Your network data doesn’t live in a vacuum. It’s very likely that some of the data you need is already there. Asset management knows device details and warranty dates. IPAM systems own IP address allocations. Circuit providers have connectivity info. Services teams have SLA details.

Don’t build another data silo. Your organization already has too many. If your source of truth can’t pull from different data sources, you’re just building spreadsheet 2.0 with an API. Nobody will maintain it. You’ll spend your life begging people to “please update the SoT” while they ignore you and keep using their existing tools.

Data Federation is not optional: pull in data from existing systems, keep it synced both ways, and present a unified view. The source of truth should be a federation layer, not a replacement database.

It helps to be precise about what “the Source of Truth” names here. It is a block, not a box. Several of its data sources already exist in your organization and already have owners: the IPAM that allocates addresses, the asset DB that tracks network components. Those systems are not outside the Source of Truth, they are part of it. What you deploy is one more data source inside the same block, and the only one that carries the network model the others cannot: call it the central SoT. Its second job is federation, joining every source in the block into one consistent view. So when this chapter says the SoT does not replace your IPAM, that is not a concession. It is a description of where the boundary actually falls.

The word “single” causes most of the remaining confusion. It gets read as all the data lives in one system, which is unachievable and beside the point. The property that matters is narrower: for any given piece of data, exactly one system decides its value. Not one system for everything, one authority per thing. Others may reference that value, cache it, or hold a copy, but they do not get to define it independently. The moment two systems both believe they decide a device’s management address, you have two values of equal standing and no rule for choosing, which is how a source of truth becomes a source of arguments.

So federation is not a compromise you settle for because consolidation failed. Having several data sources is the normal condition: organizations have different teams and domains of responsibility, and Conway’s law means your data follows those boundaries whether you plan for it or not. What the architecture owes you is not consolidation, it is unambiguous authority.

You almost certainly have data scattered across multiple systems already, each one authoritative for its own domain: HR owns the organization, asset systems own hardware details, IPAM owns IP allocations.

This is a general list of the data sources you may need to integrate with:

  • Organizational:

    • HR System: Departments, teams, roles, responsibility matrix
  • Infrastructure:

    • Asset: hardware details, serial numbers, procurement, warranty, service records
    • Cloud Platform: VPCs, subnets, security groups
    • Circuit Provider: Provisioning status, commit rate
    • IPAM: IP allocations, DHCP scopes, DNS entries
    • Configuration templates: Transformer for rendering configuration artifacts
  • Services:

    • Service Catalog: Service definitions, SLAs, customers
    • Billing System: Chargebacks, capacity planning

You may be missing the term Configuration Management Database (CMDB) above. Actually, it is many times confused with the SoT itself. The question comes up because the names overlap: a SoT is, literally, a configuration management database. However, the difference is the direction. The CMDB tracks what is in the network, populated largely by discovery and post analysis. The SoT declares what should be in the network, and the network is built from what it says. Thus, in my view, the CMDB belongs to the Observability block, and we will cover it there.

Here, domain means a data type, or a clearly delimited subset of one. The SoT orchestrates all of them into a coherent whole behind a single interface, so client applications never have to correlate five sources themselves.

When multiple systems coordinate, you need to handle conflict resolution. For example:

  • Centralized IPAM system says: 192.0.2.0/24 is allocated to customer X
  • The Service catalog says: 192.0.2.0/24 is allocated to Service A, which belongs to customer Y

Who is correct? It depends on authority designation: a governance decision that says which system gets to decide this value. Without that designation, the question has no answer, only opinions.

That designation does two jobs, and it is worth keeping them apart. It is enforced at the write boundary: a sync job from the Service catalog that tries to set a prefix is rejected, because the Service catalog does not own prefixes. And it is recorded on the record as the Data Lineage metadata, so any later reader can see which source the value actually came from. The first prevents the conflict from ever entering the data; the second explains the value months afterwards. Build only the second and you have documentation of a problem you could have refused.

For example, a resource domain ownership strategy might specify:

  • Centralized IPAM, source of truth for: IP address allocations, subnet sizes, DHCP scopes.
  • Asset system, source of truth for: asset metadata, location, and hardware model.
  • The central SoT for: interfaces and their admin state, VLANs, VLAN-to-subnet mapping, designs, and the artifacts rendered from them.

Note where the boundary falls on that last line. Admin state is the state an interface is meant to be in, which makes it intent, so it belongs with the rest of the intent. Operational state is what the network actually reports, and it belongs to Observability, many times in the form of a CMDB.

Conflict resolution strategies include:

  • Source Authority (most common): A governance decision designates one system as authoritative (e.g., the asset system is authoritative for a device’s hardware model and serial number).
  • Timestamp-based: Use last-modified timestamp; most recent change wins. Risk: Doesn’t account for corrective changes vs. mistakes
  • Contextual resolution: evaluate the surrounding context and apply a precedence rule you defined in advance.
  • Manual escalation: When confidence is medium (values differ but not contradictory), escalate to human review

Federation Architecture#

Federating data takes one of two shapes. In the centralized model the SoT pulls from each source, transforms what it gets into one schema, resolves conflicts, and serves a single view: easy to query, but every source becomes a latency and availability dependency. In the distributed model each system keeps and serves its own data while the SoT coordinates, which scales better and keeps quality with the domain that owns it, at the cost of consumers querying several places and cross-system joins getting expensive. Most real deployments sit somewhere between. Chapter 12 treats centralization versus federation as a scaling decision in its own right.

Beyond resolving conflicts, keeping data consistent across systems is the core challenge of federation. The architecture you picked above determines which synchronization approach fits:

MechanismHow the data flowsTrade-offs
Periodic sync (pull on a schedule)Every 6 hours, the SoT reads from the IPAM, compares the result with its local cache, applies the differences, and publishes its own changes back.Minutes to hours. Simple, predictable, and cheap to run, but it leaves inconsistency windows hours long and invites batch conflicts
Event-driven (message bus)The IPAM changes subnet 10.0.0.0/24 and publishes a “Subnet:Changed” event to the bus. The SoT consumes the event and updates its cache.Seconds. Responsive and close to real time, at the cost of choreography that is complex to design and harder to debug
Webhooks (direct push)The SoT registers a webhook with the IPAM. When the IPAM allocates 10.0.2.5/32, it posts the change to that webhook, and the SoT validates and stores it.Sub-second to seconds. Direct, with no message bus to operate, but the source has to support webhooks and network reliability becomes your problem
Table 5.4: Synchronization mechanisms for keeping federated data consistent.

There is no such thing as a real-time synchronization system. At best, data becomes eventually consistent, and how long “eventually” takes has to be evaluated per use case. Accept it, and design around it.

Effective federation requires clear governance, with an explicit decision recorded for each data domain.

Authority boundaries do not have to follow whole domains. The matrix below is drawn per domain because that is the common case, but the grain is yours to pick, and finer is often more honest. One IPAM can be authoritative for prefixes while a different system owns individual address assignments. Authority can split by address range, by tenant, by site, or by lifecycle stage: the IPAM owns the free pool while the SoT owns the static assignments it made itself. Any of those is fine. The only rule is that for each piece of data the answer is unambiguous, and that somebody can state it without hedging.

When nobody can state it, that is the finding. “Both systems sort of own it” is precisely the condition you are trying to eliminate, and filling in a matrix like this one is how you discover where it is still true.

A governance matrix makes those decisions explicit:

DomainAuthoritative SourceSync DirectionFrequencyConflict Resolution
Device InventoryAsset Management SystemAsset → SoT (read-only in SoT)DailyAsset always wins
Network TopologyCentral SoTSoT → reporting systemsOn changeN/A (SoT is source)
IP AllocationIPAM SystemBidirectionalHourly inbound, on change outboundIPAM wins for free-pool, SoT wins for static assignments
Table 5.5: An example data-governance matrix defining the authoritative source per data domain.

For each data element, authority metadata should track:

  • Source system: where did it come from?
  • Last sync time: when was it verified?
  • Update method: poll, push, or webhook?
  • Authority level: how trustworthy is this data?

With this metadata, the system can make informed governance decisions about data handling. Those four are the requirements; the _metadata block in Data Lineage is one encoding of them, where owner and source together carry the authority question and the sync mechanism lives with the integration rather than on each record. Persistence is what stores that block, and federation is what makes it necessary.

And when you depend on multiple systems, be ready for failure. External systems will go down. When a federated source is unavailable (e.g., IPAM down for 30 minutes), several strategies exist (pick your poison):

  1. Block operations: “Can’t allocate IP addresses without IPAM”
  2. Use cached data + mark as stale: “Using cached IPAM data from 2 hours ago; this may be inconsistent”
  3. Graceful degradation: “Can still provision devices, skip IP allocation, and queue the IP allocation for when IPAM recovers”

Federation earns everything claimed above, but none of it is free, and the costs tend to land on different people than the benefits do.

  • Every integration is a moving part. Webhooks fail silently, APIs change version, and each connection needs health monitoring of its own.
  • Overlapping attributes need explicit authority rules. The ones nobody wrote down surface later as conflicts, usually during an incident.
  • A cross-domain answer is only as good as its weakest source. A stale asset DB quietly poisons every query that touches it, and the query gives no sign that it happened.
  • Lineage and change history grow without bound. They need a retention policy of their own, decided before the storage bill decides it for you.

With the functionalities covered, the next section looks at a few situations you are very likely to face, and should be ready for.

Practical Considerations#

The functionalities above describe how a SoT operates once it is populated and trusted. Two operational realities decide whether it stays that way: how you keep the data accurate over time, and what breaks when the SoT is unavailable. Neither maps cleanly to a single functionality, and both are prerequisites for running the Intent block in practice. The third, getting the data in to begin with, is brownfield onboarding in Chapter 4.

Data Lifecycle and Reconciliation#

Data gets stale. A switch gets decommissioned without being removed from the SoT. An IP address is manually reassigned during an incident. A VLAN gets added to a trunk port by a contractor doing emergency work. Three months later, nobody remembers, and the SoT records something the network stopped being weeks ago.

Data Structure validates data on the way in. That is not enough. A record that was accurate when created can become incorrect simply because the world changed around it. Without an ongoing reconciliation process, the SoT gradually loses credibility: teams stop trusting it, start maintaining their own spreadsheets, and the automation built on top of it starts producing wrong results silently.

The reconciliation pattern means periodically comparing actual network state against the SoT and classifying every discrepancy. There are two classes:

  • Divergence: the device and the SoT disagree about something that exists in both. An IP the SoT assigns to device A is answering on device B, reassigned by hand during an incident. A VLAN deployed to a defined set of switches picked up two more trunks during troubleshooting. Detecting either is mechanical. Deciding what it means is not: the SoT may be right and the network has drifted, or the change may have been deliberate and correct, leaving the SoT stale. Nothing in the comparison itself tells you which.
  • Orphaned record: the SoT holds an object (device, prefix, VLAN) for something that no longer exists in the network. A device record still carries a management IP, but the hardware left the rack months ago, so automation aimed at that address either fails outright or, worse, reaches whatever was redeployed in its place.

The two need different handling, and divergence needs most of the thought. Picking which side is right is a judgment call, and it is the one part of reconciliation that cannot be fully automated. Where the SoT is authoritative and the change was unintended, Observability raises it and automation can remediate the device within defined guardrails. Where the change was deliberate, somebody has to answer a different question: was this an emergency fix that should now be formalized into intent, or an unauthorized change that should be reverted? Policy can settle the easy cases in advance, by class of attribute or by site, but a residue will always need a person. Orphaned records are simpler, and still should not auto-delete: surface the candidate and let someone confirm the thing is really gone.

Note what reconciliation is actually checking. The SoT and the IPAM can agree with each other perfectly and still both be wrong, because internal consistency between your systems says nothing about whether either one matches the network. Only a comparison against the live network settles that, which is why reconciliation has to read from the devices and not merely cross-check one database against another.

Brownfield onboarding is a one-time migration. Reconciliation is the operational process that keeps the SoT credible after go-live. Teams that skip reconciliation will find that trust in the SoT erodes within months, and the automation built on top of it quietly begins producing incorrect results.

The SoT as a Live Dependency#

There is a structural difference between a SoT used as a reference, read once at the start of a workflow, and one used as a live dependency, read at each step and trusted to be current. Both patterns are valid, and which one you are building is a data decision worth making deliberately rather than discovering later. The second turns SoT freshness and availability into operational requirements the first does not have: a workflow that fans out across hundreds of devices from a single snapshot read will act on stale data if anything changes underneath it, and a SoT that every automation depends on and has no high-availability design is a single point of failure for the whole platform. Chapter 12 covers the staleness window, what to do about it, and the availability design that follows.

Those are the realities any Source of Truth has to survive, whichever product it runs on. The products come next, and they matter less than you might expect.

Solutions Landscape#

There are a lot of products out there that fit the whole or part of the Intent block. Some are open source, some are commercial. Some are general purpose, some are specialized for a single domain such as IP management.

This is a snapshot as of early 2026: the landscape changes constantly, so always check current capabilities and momentum before choosing. It’s not exhaustive either, it serves as an overall reference.

Open source solutions

  • NetBox: IPAM, DCIM, circuits, devices, virtualization, inventory. The most popular of these, and the one with the largest plugin ecosystem.
  • Nautobot: IPAM, DCIM, circuits, devices, inventory. A fork of NetBox that adds a job framework, so automation workflows run inside the SoT itself.
  • Infrahub: network topology, devices, IPAM, schemas, relationships. Git-like branching and proposed-state review are built into the core rather than added on.
  • phpIPAM: IP addresses, subnets, VLANs. Straightforward IPAM on a LAMP stack, with none of the DCIM surface of the others.

Most of these are backed by a company that also sells a commercial offering and support around them. phpIPAM is the exception here: it is community-maintained.

Commercial solutions

  • ServiceNow: configuration items, services, assets, changes. The generic DB that most organizations already own, with ITIL-aligned change workflows around it.
  • Device42: data center assets, dependencies, application mapping, IPAM. Built around agentless auto-discovery, which makes it fast to onboard a brownfield estate.
  • Infoblox: DNS, DHCP, IPAM. The enterprise DNS, DHCP and IPAM authority, with multi-site replication.
  • SolarWinds IPAM: IP addresses, DHCP, DNS. Worth considering mainly if you already run the SolarWinds monitoring stack it integrates with.

When evaluating Source of Truth solutions, consider these alignment factors:

  • Scale requirements: Number of devices (hundreds vs. hundreds of thousands), rate of change, query volume
  • Data model needs: Git-based vs. Relational structure vs. graph relationships vs. flexible document store
  • Integration ecosystem: Existing tools (monitoring, ITSM, cloud platforms) that must federate data
  • Team expertise: Python/Django familiarity, preference for low-code platforms, comfort with Git workflows
  • Operational model: Self-hosted vs. SaaS, change approval processes, RBAC requirements
  • Evolution trajectory: Brownfield migration path, schema extensibility, API stability
  • Exit cost: can you export the data, the schema, and the change history in a form another system could ingest? Relationships and lineage are what products export worst, and what costs most to rebuild

Whichever product you land on matters less than whether you can answer, for your own network, the questions these two chapters have been asking: what data is in scope, what makes a value valid, where it lives and survives change, who reaches it and how, and which system decides each value. A tool answers none of those for you; it only makes your answers cheaper to implement. So the rest of this chapter works through one network and answers them end to end.

Implementation Example#

We stay with the campus network from Chapter 4: roughly 800 access and distribution switches from three vendors, spread across six buildings, A through F, carrying a steady stream of requests for new VLANs, subnets, and access changes. Three systems hold a piece of the picture, and the solution adds a fourth:

  • The IPAM, authoritative for address allocation, prefixes, and DNS.
  • The asset DB, authoritative for switch locations, hardware models, and maintenance history.
  • The switches themselves, carrying the only record of what is actually deployed.
  • The central SoT, which federates the first two and contributes the network model none of them has.

The problem. Chapter 4 followed one ordinary request through the data: a new VLAN called app-payments in Building B, expanded from three business-layer fields into technical objects and then into a per-platform artifact. That leaves the data modeled and nothing holding it. Pick the same request up here, at the point where the record has to be stored, served, and attributed.

Requirements:

  • Store the record so that two engineers changing the same service cannot corrupt it
  • Keep the complete history, and answer who changed what, when, and why, months later
  • Serve every consumer at the shape that consumer needs, from one record
  • Federate the IPAM and the asset DB rather than copying them, with one owner named per data type
  • Survive being a live dependency: a deployment must fail safely when the SoT is unreachable
  • Roll the data back without rolling back the network, and know the difference

The Functionalities in Practice#

Data Persistence: the record, its history, and its lineage

The committed object carries more than the intent:

- name: app-payments
  vlan_id: 412
  # ... intent fields omitted ...
  _version: 1
  _metadata:
    owner: "network-eng@example.net"
    source: null
    created: "2026-03-14T09:21:04Z"
    created_by: "svc-design-expander"
    change_request: "REQ-4471"
Listing 5.7: The stored record, with version, ownership, and lineage attached.

_version: 1 is what makes optimistic concurrency work: the next writer submits the version it read and is rejected if the record has moved on since, instead of silently flattening someone else’s edit. source: null says the central SoT authored the record. created_by naming a service account rather than a person is the expected case once the business layer is doing the expanding, and it is exactly why provenance has to survive machine authorship.

Data Consumption: how the data gets in and out

The request has to enter the system somewhere. An operator fills in a form, or a client posts on their behalf; either way that user-facing surface belongs to the Presentation layer (Chapter 9), not here. What reaches the SoT is a plain write against its own interface:

POST /api/vlan-services HTTP/1.1
Content-Type: application/json

{ "name": "app-payments", "building": "B", "profile": "standard" }

201 Created
Location: /api/vlan-services/9c2f1b74
Listing 5.8: Creating the service through the business-layer endpoint.

Note that the write takes the three business-layer fields, not the expanded record. The expansion happens inside the SoT, which is the only way the guardrails hold for every caller rather than only for the ones that remember to apply them.

Nothing polls for that id. When the record commits, the SoT emits a change event carrying it, and the Orchestrator is subscribed. This is the subscribe-to-change path from Data Consumption: the SoT announces that 9c2f1b74 exists and is ready to deploy, rather than waiting to be asked. The Orchestrator schedules the work, and the Executor then reads what it needs, and only what it needs:

GET /api/vlan-services/9c2f1b74?view=executor HTTP/1.1

{
  "vlan_id": 412,
  "switches": [
    { "name": "sw-b-dst-01", "platform": "vendor-b", "artifact": "/api/artifacts/9c2f1b74/sw-b-dst-01" }
  ]
}
Listing 5.9: A context-specific read: the Executor gets targets and artifacts, not the full object.

The view=executor parameter is the per-persona shaping from earlier: the Executor has no use for the cost center, the change request, or the QoS class, so it is not sent them.

Data Federation: the parts the central SoT does not own

The prefix did not come from here. The campus IPAM owns address space, so the central SoT asked for one and keeps a copy, clearly marked as a copy:

prefix:
  value: 10.12.4.0/24
  _metadata:
    owner: null
    source: "campus-ipam"
    last_synced: "2026-03-14T09:21:03Z"
Listing 5.10: A federated value: no local owner, the system it came from, and a sync timestamp.

The authority statement for this campus fits in three lines: the IPAM decides prefixes and addresses, the asset system decides which building a switch is in and what hardware it is, and the central SoT decides everything about VLAN services, designs, and the resulting artifacts. No value appears twice in that list. When a prefix needs changing, there is exactly one place to change it, and source tells any reader where that place is.

That is the whole chain: three fields in, a validated and versioned record, a per-consumer view out, and a rendered artifact per device, with every value traceable to whichever system is entitled to decide it.

The walkthrough followed one request through the data. Step back, and the components arrange themselves like this:

Solution Architecture

Figure 5.3: The implementation’s architecture.

Data Ownership and Conflicts#

How to deal with data conflicts?

The key point: the central SoT does not replace the IPAM or the asset DB, it joins them. All three are data sources inside the campus Source of Truth. The central SoT federates the other two, resolves the conflicts between them, adds the network model neither one has, and becomes the single interface that Execution, Observability, and Presentation all read from. Each team keeps the domain it already understands.

Authority, who owns what, has to be stated before any of this works, and for this campus it is short enough to fit in a table:

DataAuthorityReaches the SoT byOn conflict
Prefixes, addresses, DNSIPAM platformWebhook, within seconds of a changeIPAM wins
Asset metadata, location, hardware modelAsset DBScheduled poll, every 4 hoursAsset DB wins
VLANs, designs, service requests, rendered artifactsThe central SoTAuthored hereNot applicable
Observed device stateThe devicesDiscovery, during bootstrap onlyNever overwrites intent
Table 5.6: The campus authority matrix: exactly one owner for each kind of data.

Two rows in that table carry most of the design. Addresses arrive by webhook because an allocation is urgent and a four-hour-old view of free space produces double assignments; asset metadata polls, because a warranty date that is four hours stale harms nobody. Match the mechanism to the cost of being wrong, not to what the source happens to support.

Stating authority this way also buys something the three systems could never answer separately: cross-domain questions. Which devices in a high-security building have expired warranties? That query spans the asset DB’s data and the central SoT’s own model of what a high-security building contains, and it is answerable only because both arrive through one interface with their origins intact.

The other fundamental piece is the brownfield data discovery, which runs during bootstrap only, following the sequence in Brownfield Onboarding. The first pass will surface conflicts: an address the IPAM has allocated to one device answering on another, a VLAN present on trunks nobody recorded. Those get resolved once, by people, under a stated rule such as trust the device for access ports, trust the IPAM for infrastructure addresses. Then the direction flips, and skipping that flip is the most common way a SoT quietly turns back into a report.

Notice in the figure that discovery feeds the network model directly, rather than passing through the federation layer. That is deliberate. Federation exists to arbitrate between systems that keep owning their data; discovery produces a one-time snapshot that nobody owns afterwards. Routing it through federation would imply the devices hold a standing authority claim over intent, which is precisely the inversion the flip is there to end.

When a source goes away

Federation makes other people’s uptime part of yours, so decide the degraded behavior before you need it. For this campus:

  • The SoT keeps serving its last known copy of the IPAM data, stamped with how old it is.
  • Operators see that staleness without asking: “address data is 2 hours old, the IPAM is unreachable, new allocations are deferred.”
  • Requests needing a fresh allocation queue instead of guessing, and drain when the IPAM returns.
  • Everything that does not need a new address carries on: onboarding a switch, editing a design, rendering a config from data already held.

That last bullet is the one worth designing for. A federation that halts entirely whenever any source is down has turned several systems’ availability into one shared point of failure, which is precisely what it was built to avoid.

Other campuses will land on other shapes, and that is fine. What transfers is not the diagram but the sequence behind it: name the data, name its owner, pick a sync mechanism that matches how expensive staleness is, and decide in advance what happens when a source you do not control stops answering.

This concrete example generalizes into a short getting-started list:

Getting Started#

Chapter 4 covered the first three steps, the ones about the data: pick the objects you need, model them without starting from a blank page, and decide how high-level the entry point should be. Three more follow, and they are this chapter’s.

  1. Settle how the data is reached and who may change it. Which systems read, which write, and through what interface. Then the authorization questions: who edits data, and separately, who edits the schema. Doing this on paper is faster than discovering it from an incident.

  2. Name the owner of each piece, and federate the rest. List the systems that already hold authoritative data and write down, per data type, which one wins. If a source turns out to be a spreadsheet nobody maintains, retire it now rather than wiring it in. Early is cheap.

  3. Then actually use it. This is the step that determines whether any of the other five mattered. An SoT that nothing depends on degrades into a documentation page that drifts quietly out of date. Pick one real operation and make its configuration come from the SoT, even if the Executor does not exist yet and someone pastes the rendered artifact by hand. Something has to depend on the data for the data to stay true.

Hopefully these two chapters have clarified the relevance of the Source of Truth within the network automation architecture, and what to weigh when building one. Let’s summarize the key points.

Summary#

The firewall rule in the opening story outlived its service by six months because nothing recorded that the two belonged together. Nobody failed to do their job, and no system held wrong data. What was missing was a system around the data: one interface over the five sources, provenance on every value, and a process that keeps comparing what the records claim against what the network is actually running.

Three functionalities supply that. Data Persistence keeps the intent safe across concurrent writers, records every change for audit and rollback, and carries the lineage metadata that says who owns each value and where it came from. The store you pick for it also fixes which questions are cheap to ask. The expensive ones are the queries that cross several relationships, which is most of what anyone asks of a network model. Data Consumption serves it to humans, workflows, and agents at the right shape for each, and governs who may read data, who may change it, and separately who may change the schema. Data Federation connects the SoT to the systems that already hold authoritative data, on the principle that matters most here: not one system for everything, but exactly one authority per piece of data.

Two realities then decide whether any of it survives contact with a real network. Reconciliation means a record that was correct when written can quietly stop being correct, so something has to keep comparing intent against reality, and a person has to settle which side is right. And once automation depends on the SoT at run time, the SoT’s availability becomes the platform’s availability.

None of it matters, though, until a real operation depends on the data, which is why the last step of getting started is the one that counts.

Chapter 6 takes that intent and turns it into action: the Execution block reads from the SoT and pushes changes to the network, relying on the consistent network intent these two chapters have described.

References#

  • Designing Data-Intensive Applications, Martin Kleppmann (O’Reilly, 2017). Consistency, replication, and data-modeling trade-offs; the theoretical grounding for the persistence and federated-data patterns in this chapter.
  • Enterprise Integration Patterns, Gregor Hohpe and Bobby Woolf (Addison-Wesley, 2003). Data integration and aggregation patterns for federating multiple authoritative sources into a coherent SoT.
  • Master Data Management, David Loshin (Morgan Kaufmann, 2008). Federated governance, data ownership, and authoritative-source design; the enterprise-data foundation for treating the SoT as managed master data.

💬 Found something to improve? Send feedback for this chapter