Domain 3 of 4 · Chapter 1 of 6

Model-Driven Telemetry Architecture

From SNMP polling to a telemetry subscription

A collector that SNMP-polls interface counters on five hundred switches every thirty seconds sends thirty thousand GET requests a minute and still misses anything that moved between two polls. Model-driven telemetry (MDT)[1] inverts that arrangement: you create one subscription on the device that names the data you want, and from then on the device streams the updates to your collector on its own. This page is a map of that whole path, from the subscription down to the dashboard.

MDT is a replacement for SNMP, not a repackaging of it. The data it streams is YANG-modeled operational state, and it rides gRPC, gNMI, or NETCONF, so nothing in the stack uses SNMP traps, MIB OIDs, or an SNMPv3 "encoding". That distinction is tested directly: an option that lists SNMPv3 or MIB OIDs as a component of an MDT subscription is wrong by construction, because Cisco positions MDT as the push-model successor to periodic SNMP polling[1], not a layer on top of it.

One pipeline, five stages

Every MDT deployment is the same pipeline, and the figure traces its five stages. The device selects data with a sensor path, encodes the reading as a GPB variant or JSON, a transport carries it, the collector decodes it, and finally stores and visualizes it. Two properties of the subscription govern that flow and get their own sections next: the subscription model (who dials whom, and whether it persists) and the trigger (how often an update is sent). Read any telemetry ietf subscription block as answers to these questions and it stops being a wall of keywords.

Sensor path device selects Encode GPB or JSON Transport gRPC / gNMI / NETCONF Decode collector Store + view InfluxDB / Grafana
The MDT pipeline: the device selects a sensor path, encodes the reading, a transport carries it, and the collector decodes, stores, and visualizes it.

Subscription models: dial-in and dial-out

Two collectors ask the same router for the same interface counters. One opened a session, subscribed, and loses everything the moment that session drops; the other is named in the router's configuration, and the router keeps calling it through reloads until an operator removes it. Those are the two flavors of MDT subscription, and telling them apart is most of this topic.

Two questions describe any subscription, and Cisco couples their answers. The first is who opens the transport connection: in a dial-in subscription the collector opens it to the device, and in a dial-out subscription the device opens it to the collector. The second is how the subscription is created and whether it survives: a dynamic subscription is created at runtime by an establish-subscription RPC[2] over an already-open session, while a configured subscription is written into the running-config[2] and persists. The coupling is the rule the rest hangs on: dynamic subscriptions are always dial-in and configured subscriptions are always dial-out[1]. A "dial-out dynamic" subscription is the classic trap, because it does not exist.

Dial-in dynamic: the collector owns it

The collector, acting as client, opens a NETCONF or gNMI session to the device and creates the subscription over that same connection; the device is the server answering an inbound call and never dials the other way. The subscription lives only for that session, is never saved to configuration, and cannot survive a reload. The single most common misread is that the device initiates a dial-in session, but it is always the collector that dials in.

Dial-out configured: the device owns it

A dial-out subscription is written into the running-config, and the device initiates the connection to the receiver you name, so it persists across reloads and the device keeps retrying a receiver that is down. The mirror-image trap is assuming the collector initiates in dial-out; it does not.

Reading the subscription id

The id itself tells you which flavor you are looking at. A configured subscription carries an operator-assigned id[1] you choose in the range 0 to 2147483647, while a dynamic subscription is given a server-assigned id from the upper half of the 32-bit range, 2147483648 and above, at session establishment. A small, human-looking id is therefore configured and dial-out; a large machine id is dynamic and dial-in.

Two axes Cisco couples them Dial-in collector opens the connection Dial-out device opens the connection Dynamic created by an RPC non-persistent Configured created in config persistent Dial-in dynamic collector subscribes over its own session; torn down at disconnect Not a valid combination "dial-out dynamic" does not exist Not a valid combination a configured subscription is always dial-out Dial-out configured device streams from its running-config; persists across reload
The two coupled axes of MDT subscriptions: only dial-in dynamic and dial-out configured exist; dial-out dynamic and dial-in configured are not valid.

Sensor paths and triggers: what streams, and when

Two more choices decide what actually streams: which nodes, and when. Both live in a couple of lines of the subscription, and the exam leans on reading them correctly.

The sensor path scopes the data

A sensor path is a YANG XPath[3] that names exactly which nodes the device publishes, set with filter xpath inside the subscription; nothing outside it is streamed. Read Cisco-IOS-XE-interfaces-oper:interfaces/interface/statistics left to right: the leading token is the YANG module, interfaces is a container, interface is the list of interfaces, and statistics is the per-interface counter sub-tree. Shorten the path and you stream more of each interface; deepen it to .../statistics/in-octets and you stream a single leaf. The shape of the data under the path also hints at the trigger, which is why the figure marks which sub-trees lean which way.

Periodic streams on a timer; on-change streams on a delta

A periodic subscription publishes the path's data every configured interval whether or not it changed, which fits counters that move on every tick. On IOS XE the period is expressed in centiseconds[3], so update-policy periodic 3000 fires every 30 seconds and the minimum, 100, is one second. Reading that number as seconds is the single highest-yield misread on this topic: divide by 100. An on-change subscription is edge-triggered, sending an update only when a subscribed value actually changes and staying silent otherwise, which fits mostly-stable state such as an interface's oper-status. On-change is quieter than periodic on stable data, not "continuous"; its real risk is a burst when a value flaps, which a dampening period bounds, and it works only where the platform advertises the path as on-change capable.

A complete configured dial-out subscription on IOS XE ties the two choices together:

telemetry ietf subscription 101
 encoding encode-kvgpb
 filter xpath /memory-ios-xe-oper:memory-statistics/memory-statistic
 stream yang-push
 update-policy periodic 6000
 receiver ip address 10.28.35.45 57555 protocol grpc-tcp

filter xpath is the sensor path, stream yang-push selects the datastore-push stream, update-policy periodic 6000 is the trigger at 60 seconds, and receiver is the dial-out destination. Swap update-policy periodic 6000 for update-policy on-change on a status path such as .../interface/oper-status and the timer disappears entirely.

Which RFC owns which idea

RFC 8639[2] defines the subscription mechanism: the dynamic-versus-configured lifecycle and the subscription-started, -modified, and -terminated state notifications. RFC 8641 (YANG-Push)[4] builds on it to add datastore subscriptions with the periodic and on-change triggers. A question about how a subscription is created points at 8639; a question about when an update fires points at 8641.

Cisco-IOS-XE-interfaces-opermodule (its XPath prefix leads the path)interfacesinterfacecountersstatestatisticscounters (use periodic)oper-statusstable state (use on-change)A sensor path selects a sub-tree; a deeper path streams fewer nodes.
One operational-model tree: a sensor path selects a sub-tree. A statistics path is counters (fits periodic); an oper-status leaf is stable state (fits on-change).

Transport: gRPC, gNMI, and NETCONF

The subscription names a transport, and MDT is deliberately not tied to any single one. Three transports carry it on Cisco platforms, and each pairs naturally with a subscription model from the previous section, as the figure's three stacks show.

Native gRPC dial-out

The common production transport is native gRPC dial-out[1]: the device streams to a gRPC receiver whose IP address and port are named in the configured subscription's receiver clause, called a destination-group on IOS XR. Because the device initiates, this is always a dial-out configured subscription, and it is the transport behind a receiver ip address 10.28.35.45 57555 protocol grpc-tcp line.

gNMI over gRPC

gNMI, the gRPC Network Management Interface[5], is a management protocol built on gRPC, and its Subscribe RPC carries the telemetry stream for dial-in collection. The stack underneath is worth memorizing: gNMI runs on gRPC, gRPC runs on HTTP/2, and TLS secures the channel[5]. The trap is to think gNMI rides plain TCP or SNMP; it does neither, sitting on HTTP/2 over TLS. A gNMI subscription is dial-in, so the collector opens the gRPC session and issues the Subscribe RPC.

NETCONF-carried YANG-Push

MDT does not require gRPC at all. The same RFC 8639 and 8641 YANG-Push[2] subscriptions can be carried over NETCONF[6] on its SSH transport as dynamic dial-in subscriptions. Assuming MDT is gRPC-only is a common error: NETCONF-over-SSH is a first-class dial-in transport for the identical periodic and on-change subscriptions, differing only in the wire it runs on.

Native gRPC dial-out gRPC HTTP/2 TLS TCP gNMI (Subscribe RPC) gNMI gRPC HTTP/2 TLS NETCONF YANG-Push NETCONF SSH TCP device dials the receiver collector dials in collector dials in One YANG-Push subscription; three interchangeable transports
Three MDT transports as protocol stacks: native gRPC dial-out, gNMI (Subscribe RPC) over gRPC/HTTP2/TLS, and NETCONF over SSH.

Encoding: JSON, KVGPB, and compact GPB

The encoding decides whether your collector can read a single byte of the stream, and it is named per subscription, not set once for the whole device. That is why one router can export readable JSON on a debugging subscription and compact binary on a production one at the same time.

MDT serializes the same sensor data three ways. JSON is UTF-8 text, the largest on the wire but readable by eye. Self-describing GPB, also called key-value GPB or KVGPB, is a binary format where every value travels with its field name, so one generic telemetry.proto decodes any sensor path[7]. Compact GPB is the same Google Protocol Buffers wire type with the names stripped out, the smallest and least self-contained. gRPC dial-out on IOS XE carries KVGPB[8], while gNMI negotiates JSON, JSON_IETF, or PROTO in its Subscribe request. The claim that "MDT only uses JSON" is therefore false, and it is the classic encoding trap.

Compact GPB needs the .proto

Compact GPB is smaller for exactly one reason, and that reason is the whole trade-off: it omits the field keys, so the collector must already hold the exact .proto compiled for that sensor path[9] to know what each value means. KVGPB embeds the keys, so a generic collector decodes it with no model-specific schema. This is why compact GPB and KVGPB are not interchangeable at the collector even though both are "GPB": a generic collector reads KVGPB and JSON as they arrive but silently fails on a compact-GPB stream whose .proto it lacks. When a stem says one device's stream is undecodable on a collector that reads the others fine, the cause is compact GPB missing its .proto, and the fix is to switch that subscription to self-describing GPB.

An MDT stream arriveshow is it decoded?JSONparse as textno .proto neededSelf-describing GPBone telemetry.protodecodes any pathCompact GPBper-path .protorequiredMissing .proto= decode failstextkeys embeddedkeys stripped
Decoding by encoding: JSON parses as text, KVGPB uses the generic telemetry.proto, and compact GPB needs the per-path .proto or it fails.

The collector: the TIG pipeline

At the far end of the pipeline sits the collector, and the most common one is the TIG stack: three open-source tools with one job each, swappable independently.

Telegraf[10] is the only stage that has to understand MDT. Its cisco_telemetry_mdt input plugin terminates the gRPC dial-out session and decodes the GPB or JSON payload into flat measurements; for gNMI dial-in you swap in the sibling cisco_telemetry_gnmi plugin, which is exactly why the encoding decision lives entirely in this stage. InfluxDB is a time-series database that stores each decoded reading against its timestamp. Grafana then queries InfluxDB to render dashboards[10] and never sees GPB, only the numbers Telegraf already decoded.

That separation is the useful part. Because only Telegraf touches the encoding[11], a dashboard showing no data is almost always a decode-stage failure such as a wrong listener port, a missing .proto for compact GPB, or a TLS mismatch, not a problem inside InfluxDB or Grafana. Map decode to Telegraf, storage to InfluxDB, and visualization to Grafana; swapping the last two is the common wrong pairing on the exam.

RoutergRPC dial-out :57555Telegraf (decode)cisco_telemetry_mdtInfluxDBtime-series storeGrafanadashboardspushwritequery
The TIG collector: the router dial-outs over gRPC to Telegraf, which decodes and writes to InfluxDB, and Grafana queries InfluxDB for dashboards.

Exam patterns: the traps that decide items

Most 350-901 telemetry items are classification: a config block or a sentence, and a question about what streams, how often, or which standard governs it. A handful of traps account for most wrong answers, and each maps to one line of a subscription.

The subscription-model coupling settles the first group. Device-initiated push is always a configured dial-out subscription, and an RPC-created dynamic subscription is always dial-in, so "dial-out dynamic" and "dial-in configured" are both impossible; an option pairing "dynamic" with "the device connects to the collector" contradicts the coupling and is wrong on its face. The subscription id is a second tell: a small operator-chosen id is configured and dial-out, while a large id in the upper half of the 32-bit range was server-assigned and is dynamic and dial-in.

The trigger group turns on two facts. A periodic period is in centiseconds, so update-policy periodic 3000 is 30 seconds, not 3000; divide by 100. And on-change sends nothing until a value moves, then one update, so any answer calling it "continuous" or "more frequent than periodic" has the model backwards.

The transport and encoding group has its own reflexes. MDT streams YANG-modeled data over gRPC, gNMI, or NETCONF and never uses SNMP OIDs or traps, so an "SNMPv3 encoding" option is never part of an MDT subscription. gRPC dial-out commonly uses KVGPB, so MDT is not JSON-only, and gNMI is HTTP/2 over TLS, not plain TCP. Finally, compact GPB and KVGPB share a wire type but are not interchangeable at the collector: only KVGPB is self-describing, so a compact-GPB stream still needs the model's .proto.

The stem shows Right reading The trap it sets
The device connects out to a named receiver Dial-out configured; persists across reloads "The collector initiates in dial-out"
A collector connects and subscribes at runtime Dial-in dynamic; torn down at disconnect "The device initiates the dial-in session"
update-policy periodic 3000 30 seconds (centiseconds divided by 100) Reading 3000 as seconds
update-policy on-change Silent until a subscribed value changes "Streams continuously like periodic"
A subscription id such as 3200000000 Server-assigned, so dynamic and dial-in "A large id is operator-assigned"
One device undecodable on a collector that reads others Compact GPB missing its .proto; use KVGPB "Restart InfluxDB or rebuild Grafana"
"SNMPv3 encoding" listed as an MDT component Invalid; MDT streams YANG data, not SNMP Treating MDT as repackaged SNMP

Dial-in (dynamic) vs dial-out (configured) subscriptions

PropertyDial-in (dynamic)Dial-out (configured)
Who opens the connectionCollector connects to the deviceDevice connects to the receiver
How it is createdestablish-subscription RPC (NETCONF/gNMI)running-config (telemetry ietf subscription)
PersistenceEnds when the session dropsSurvives session loss and reload
Subscription IDServer-assigned, 2147483648-4294967295Operator-assigned, 0-2147483647
Who can modify/remove itOnly the originating subscriberAny privileged operator, via config

Decision tree

Must it survive a session drop or a reload? Yes No Dial-out configured persists across reload Will the collector open the session (dial in)? Yes No Dial-in dynamic collector subscribes; torn down with session Can the device reach the receiver on a set port? Yes No Dial-out configured device dials out; even short-term Neither works yet fix device-to-receiver reachability first Device-initiated push always means a configured (dial-out) subscription: there is no dial-out dynamic.

Sharp facts the exam loves — give these one last read before exam day.

Cheat sheet

Sharp facts the exam loves — scan these before test day.

Dial-in dynamic subscriptions

In dial-in (dynamic) MDT the collector/client initiates the gRPC session to the device and creates a subscription that lives only for the duration of that session; when the client disconnects the subscription is torn down.

Trap Assuming the device (not the collector) initiates a dial-in session.

7 questions test this
Dial-out configured subscriptions

In dial-out (configured) MDT the subscription is statically configured on the device (via CLI or NETCONF) and the DEVICE initiates the connection to the receiver; it persists across sessions and reloads.

Trap Thinking the collector initiates the connection in dial-out mode.

7 questions test this
Dynamic couples to dial-in, configured to dial-out

In Cisco IOS-XE MDT the axes are coupled: dynamic subscriptions are always dial-in and non-persistent, configured subscriptions are always dial-out and persistent; 'dial-out dynamic' is not a valid combination.

Trap Choosing a 'dial-out dynamic' subscription, which does not exist.

6 questions test this
Subscription identifiers

A configured (dial-out) subscription is identified by an operator-assigned subscription-id in the device config; a dynamic (dial-in) subscription receives a server-assigned id at session establishment.

3 questions test this
gNMI runs over gRPC on HTTP/2

gNMI (gRPC Network Management Interface) runs over gRPC, which uses HTTP/2 as its transport, and TLS secures the channel; a gNMI Subscribe RPC carries the telemetry stream.

Trap Believing gNMI runs over plain TCP or SNMP.

6 questions test this
Native gRPC dial-out to a receiver

Native gRPC dial-out streams telemetry from the device to a gRPC receiver whose address and port are named in the configured subscription's receiver/destination-group.

2 questions test this
NETCONF-carried YANG-Push

MDT can also be carried over NETCONF using RFC 8639/8641 YANG-Push notifications on the NETCONF-over-SSH transport for dial-in subscriptions, not only over gRPC.

Trap Believing MDT requires gRPC exclusively.

2 questions test this
MDT replaces SNMP polling

Model-driven telemetry replaces SNMP polling: it streams YANG-modeled data and does not use SNMP traps or MIB OIDs for encoding or transport.

Trap Selecting SNMPv3 encoding or MIB OIDs as an MDT component.

2 questions test this
Periodic subscriptions

A periodic subscription streams the sensor-path data every configured period; on IOS-XE the period is expressed in centiseconds (period 3000 = 30 seconds), regardless of whether the value changed.

Trap Reading the IOS-XE period value as seconds instead of centiseconds.

7 questions test this
On-change subscriptions

An on-change subscription sends an update only when a value in the subscribed path changes, minimizing bandwidth for state that is mostly stable (e.g. interface admin/oper status).

Trap Assuming on-change streams continuously like periodic.

6 questions test this
Sensor paths anchor the data scope

A sensor-path is the YANG XPath identifying the data to stream (e.g. Cisco-IOS-XE-interfaces-oper:interfaces/interface/statistics); it defines exactly which nodes the subscription publishes.

5 questions test this
YANG-Push and subscription RFCs

RFC 8641 (YANG-Push) defines datastore subscriptions with periodic and on-change semantics; RFC 8639 defines the underlying dynamic and configured subscription mechanism.

KVGPB vs JSON encoding

gRPC dial-out MDT commonly encodes data as KVGPB (key-value Google Protocol Buffers) for compactness, while gNMI and other transports can use JSON or JSON_IETF; the subscription names the encoding.

Trap Assuming MDT only ever uses JSON encoding.

5 questions test this
Compact vs self-describing GPB

Compact GPB needs the matching .proto file to decode because it omits field keys, whereas self-describing GPB (KVGPB) embeds keys so a generic collector can decode without the .proto.

Trap Treating compact GPB and KVGPB as interchangeable at the collector.

4 questions test this
TIG collector pipeline

A common MDT collection pipeline is the TIG stack: Telegraf (the cisco_telemetry_mdt input plugin decodes the stream) -> InfluxDB (time-series store) -> Grafana (visualization).

References

  1. https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/prog/configuration/1718/b-1718-programmability-cg/model-driven-telemetry.html
  2. https://datatracker.ietf.org/doc/html/rfc8639
  3. https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/prog/configuration/1715/b_1715_programmability_cg/m_1715_prog_ietf_telemetry.html
  4. https://datatracker.ietf.org/doc/html/rfc8641
  5. https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/prog/configuration/1718/b-1718-programmability-cg/gnmi.html
  6. https://datatracker.ietf.org/doc/html/rfc6241
  7. https://www.cisco.com/c/en/us/td/docs/routers/crs/software/crs-r6-7/telemetry/configuration/guide/b-telemetry-cg-crs-67x/core-components-of-telemetry.html
  8. https://www.cisco.com/c/en/us/td/docs/ios-xml/ios/prog/configuration/1714/b_1714_programmability_cg/m_1714_prog_ietf_telemetry.html
  9. https://www.cisco.com/c/en/us/td/docs/iosxr/ncs5500/telemetry/b-telemetry-cg-ncs5500-62x/b-telemetry-cg-ncs5500-62x_chapter_010.html
  10. https://www.cisco.com/c/en/us/support/docs/wireless/catalyst-9800-series-wireless-controllers/222054-configure-advanced-grpc-workflow-with-te.html
  11. https://developer.cisco.com/learning/modules/ansible-mdt/08-exploring-tig/influxdb-and-the-grafana-dashboard/