skip to content

Modules and Submodules

A module has a namespace, a prefix and revisions, and pulls in others by import or include. Resolving that dependency graph is the first thing any YANG tooling does, and the first thing that breaks.

on this pageshow

questions

5

In a YANG module, what do the namespace and prefix statements each do, and which one identifies the module's data on the wire?

level: juniorimportance: must knowfreq 20%

answer

  1. one is global, one is local
  2. a URI that never changes
  3. importers may pick their own
  4. XML by URI, JSON by module name

basics

~20 s

A YANG namespace is a globally unique URI that qualifies the module's definitions and never changes; the prefix is a short local handle an importer may rename. Encoded data uses the namespace in XML and the module name in JSON, never the prefix.

solid answer

~40 s

Every YANG module header carries exactly one `namespace` and exactly one `prefix` (RFC 7950 §7.1.1). The `namespace` is a URI — `urn:ietf:params:xml:ns:yang:<module-name>` for IETF standard modules, an organization-owned URI otherwise — and the module's elements are qualified by it in the XML encoding, which is why §11 forbids changing it after publication. The `prefix` is only the module's suggested short name: it may qualify local names, and each importer assigns its own prefix inside its `import` statement, reusing the module's one unless two imports clash. Because prefixes are local, no encoding relies on them for identity: XML uses the namespace URI, while the JSON encoding (RFC 7951) and RESTCONF paths (RFC 8040) qualify names with the module name, as in `ietf-interfaces:interfaces`.

code

yang · 20 lines
yang
module example-system {
  yang-version 1.1;
  namespace "urn:example:system";
  prefix sys;

  import ietf-interfaces {
    prefix intf;   // local choice; the module's own prefix is if
  }
  import ietf-yang-types {
    prefix yang;
  }

  organization "Example Org";
  contact "[email protected]";
  description "Documentation example.";

  revision 2026-03-01 {
    description "Initial revision.";
  }
}

go deeper

for a junior

Recall the three identities: module name and namespace are global and permanent, the prefix is a local nickname. Name which one XML uses and which one JSON uses.

for a middle

Explain the import prefix: the importer chooses it, should reuse the module's own, and must rename on a clash. Show that a submodule's data lands in its module's namespace.

for a senior

Show the operational consequence: client code keyed on prefixes breaks when a server or importer picks another prefix, while code keyed on namespace or module name survives every revision.

for a principal

Argue for namespace and naming policy across an estate's private modules: an owned URI scheme, organization-wide module-name prefixes, and why neither may ever be recycled.

## Three names for one module A YANG module (RFC 7950 defines YANG 1.1; RFC 6020 still defines version 1) is identified in three different ways, and interview answers often blur them: | Name | Statement | Scope | May it change after publication? | |---|---|---|---| | **Module name** | `module <name>` | Global — unique within a server and, for published modules, in the IANA "YANG Module Names" registry | No (§11) | | **Namespace** | `namespace "<URI>"` | Global — a URI that must not collide with anyone else's | No (§11) | | **Prefix** | `prefix <identifier>` | Local — inside one module or submodule's text | Yes, if every local use changes with it (§11) | The module substatement table in §7.1.1 makes `yang-version`, `namespace` and `prefix` mandatory, exactly once each. A module with no `yang-version` statement, or with the value `1`, is a YANG version 1 module under RFC 6020; a YANG 1.1 module must say `yang-version 1.1;`. ## The namespace: global and permanent The `namespace` statement binds the module to an XML namespace — a globally unique URI. In the XML encoding that NETCONF carries, the module's elements are qualified by that URI — including nodes it instantiates from an imported grouping, which take the namespace of the module that uses the grouping (§7.1.3). Two consequences follow: - **It has to be unique.** RFC 7950 §5.3 says namespaces for modules published in RFC streams are assigned by IANA, while private modules choose a URI their organization owns so it cannot collide — for example `https://example.com/ns/example-system` or `urn:example:system`. - **It cannot change.** RFC 7950 §11 says the `namespace` statement MUST NOT be changed, since all XML elements are qualified by it. Changing it would make every stored and transmitted instance belong to a different module. RFC 9907, the authoring guidelines, recommends the form `urn:ietf:params:xml:ns:yang:<module-name>` for Standards Track modules, so the URI usually repeats the module name — a convention that helps humans, not a rule the language enforces. ## The prefix: a local alias The `prefix` statement plays two roles (RFC 7950 §7.1.4): 1. **Inside the module itself** it is the module's own short name, which the module may use on its local definitions and which it suggests to importers. 2. **Inside an `import` statement** it is the handle *the importer* chooses for the imported module; references then read `if:ifIndex`, `yang:counter64` and so on. An importer SHOULD reuse the module's own prefix, but if two imported modules declare the same prefix, at least one MUST be imported under a different one. All prefixes used inside one module or submodule, its own included, must be unique there. Because the prefix belongs to the text of one module, two modules can import the same module under two different prefixes without any conflict at all. ## What actually travels on the wire The encodings never treat a prefix as identity: - **XML (NETCONF)** qualifies elements by namespace URI. An XML namespace prefix appears in the document, but it is just an XML alias; RFC 7950 asks clients and servers to use the module's own prefix there for readability, unless that conflicts. - **JSON (RFC 7951)** qualifies a member name with the **module name**: `"ietf-interfaces:interfaces"`. Data defined in a submodule takes the name of the module it belongs to. - **RESTCONF (RFC 8040)** builds resource paths from the same `module-name:identifier` form. So "the prefix is what identifies my data" is wrong in every encoding, and a client that matches XML elements by prefix rather than by namespace URI breaks as soon as a server uses a different XML prefix. ## The rest of the header A complete header also carries meta-information and history: - `organization`, `contact` and `description` — optional in the grammar, but RFC 9907 requires all three in published modules. - `revision` statements, newest first, each dated `YYYY-MM-DD` — the module's version history. - `import` and `include` — the linkage to other modules and to the module's own submodules. ## Common mistakes - Treating the prefix as globally registered identity. IANA's registry records a module's prefix, but an importer may still choose another. - Assuming the namespace can be "bumped" to signal a new version — the revision date does that; the namespace stays. - Forgetting that a submodule has no namespace or prefix of its own: its definitions live in the namespace of the module it belongs to.

  • Why does RFC 7950 forbid changing a published module's namespace but allow changing its prefix?
    Every encoded instance depends on the namespace: XML elements are qualified by it, so a new URI would turn existing data into another module's data. The prefix lives only inside the module's own text, so §11 allows changing it as long as every local use is changed too; importers never depended on it because they choose their own.
  • Two modules you import both declare the prefix `ex`; what must your module do?
    Import at least one of them under a different prefix. RFC 7950 §7.1.4 says the module's own prefix SHOULD be reused on import unless there is a conflict, and that all prefixes within one module or submodule MUST be unique, so a clash is resolved locally without touching either imported module.

saying these in an interview costs you the question

  • The prefix is the module's global identity and cannot be changed by importers.
  • JSON-encoded YANG data qualifies member names with the module's prefix.
  • You bump the namespace URI to publish a new version of a module.
  • A submodule declares its own namespace for the definitions it contributes.
  • yang-version is optional in YANG 1.1 and defaults to the newest version.
open as a page

In YANG, how does import differ from include, and what does a submodule's belongs-to statement tie it to?

level: middleimportance: must knowfreq 22%

basics

~20 s

In YANG, import references another module's definitions through a local prefix while that module keeps its own namespace; include merges one of the module's own submodules into it. A submodule's belongs-to names the single module it is part of.

open as a page

Why must every published change to a YANG module add a new revision statement, while its name and namespace stay fixed?

level: middleimportance: should knowfreq 14%

basics

~20 s

A YANG module's revision date is its version: importers pin it and servers report it, so each published change needs a new, later date. Name and namespace are permanent identity; an incompatible change needs a new identifier.

open as a page

An automation repository cannot compile a vendor's YANG module because an imported module is missing; how do you resolve its dependency graph?

level: seniorimportance: should knowfreq 12%

basics

~20 s

Walk the YANG module's import and include statements recursively, collecting every module and submodule. A revision-date demands that exact revision; an unpinned import may resolve to any revision, so supply one that defines everything referenced, before compiling.

open as a page

Two YANG modules in one toolchain import different revisions of the same module; when is that legal, and what goes wrong?

level: seniorimportance: nice to knowfreq 7%

basics

~20 s

It is legal: each YANG importer takes typedefs, groupings and identities from the revision it pins. But a server implements only one revision, so schema nodes come from that one, and same-named types can differ in value space.

open as a page