diff --git a/doc/source/contributor/figures/neutron-metadata-dhcp-agent.dot b/doc/source/contributor/figures/neutron-metadata-dhcp-agent.dot
new file mode 100644
index 00000000000..d69573acefd
--- /dev/null
+++ b/doc/source/contributor/figures/neutron-metadata-dhcp-agent.dot
@@ -0,0 +1,105 @@
+/*
+neutron-metadata-dhcp-agent
+
+Edit this file, instead of the corresponding png/svg.
+Those can be re-generated by:
+sudo apt install graphviz
+dot -T svg -o out.svg in.dot
+dot -T png -o out.png in.dot
+*/
+
+digraph {
+
+ compound = true
+ node [
+ shape = record
+ ]
+
+ subgraph cluster_openstack_controller {
+ label = "openstack controller node"
+ nova_metadata [
+ label = "nova metadata service"
+ ]
+ public_openstack_api [
+ label = "public openstack APIs\n(nova, neutron)"
+ ]
+ }
+
+ subgraph cluster_openstack_network {
+ label = "openstack network node"
+ neutron_dhcp_agent [
+ label = "neutron-dhcp-agent"
+ ]
+ neutron_metadata_agent [
+ label = "neutron-metadata-agent\n\nadds HTTP headers:\nX-Tenant-ID: project-UUID\nX-Instance-ID: instance-UUID\nX-Instance-ID-Signature: ...\n\nremoves HTTP header:\n X-Neutron-Network-ID"
+ ]
+ subgraph cluster_neutron_dhcp_namespace {
+ label = "neutron DHCP namespace\n(for isolated tenant net)"
+ neutron_dhcp_ns_metadata_proxy [
+ label = "neutron ns-metadata-proxy\n\nadds HTTP headers:\nX-Forwarded-For: instance-IP\nX-Neutron-Network-ID: network-UUID"
+ ]
+ metadata_lla [
+ label = "169.254.169.254/32\nconfigured in namespace"
+ ]
+ neutron_dhcp_server [
+ label = "neutron DHCP server"
+ ]
+ }
+ }
+
+ subgraph cluster_tenant_net_isolated {
+ label = "isolated tenant net\n(i.e. without gateway)"
+ instance [
+ label = "openstack instance\nno 169.254 IP configured locally"
+ ]
+ }
+
+ response_omitted [
+ label = "the response is omitted for brevity..."
+ shape = plaintext
+ ]
+
+ metadata_lla -> instance [
+ label = "HTTP GET\n169.254.169.254:80"
+ dir = back
+ align = left
+ ]
+
+ neutron_dhcp_ns_metadata_proxy -> metadata_lla [
+ label = "metadata\ntraffic"
+ dir = back
+ align = left
+ ]
+
+ neutron_metadata_agent -> neutron_dhcp_ns_metadata_proxy [
+ label = "unix socket"
+ dir = back
+ ]
+
+ neutron_dhcp_server -> instance [
+ label = "pushes static route:\n169.254.169.254 via dhcp-port-IP"
+ ]
+
+ neutron_dhcp_agent -> neutron_dhcp_server [
+ label = "configures\nstatic leases\nand dhcp options"
+ ]
+
+ neutron_dhcp_agent -> neutron_dhcp_ns_metadata_proxy [
+ label = "starts"
+ ]
+
+ nova_metadata -> neutron_metadata_agent [
+ dir = back
+ ]
+
+ public_openstack_api -> neutron_metadata_agent [
+ label = "looks up instance UUID"
+ dir = back
+ ]
+
+ nova_metadata -> response_omitted
+ response_omitted -> neutron_metadata_agent [
+ style = invis
+ ]
+
+}
diff --git a/doc/source/contributor/figures/neutron-metadata-dhcp-agent.png b/doc/source/contributor/figures/neutron-metadata-dhcp-agent.png
new file mode 100644
index 00000000000..f04a5f97545
Binary files /dev/null and b/doc/source/contributor/figures/neutron-metadata-dhcp-agent.png differ
diff --git a/doc/source/contributor/figures/neutron-metadata-dhcp-agent.svg b/doc/source/contributor/figures/neutron-metadata-dhcp-agent.svg
new file mode 100644
index 00000000000..4a93eb0ad8d
--- /dev/null
+++ b/doc/source/contributor/figures/neutron-metadata-dhcp-agent.svg
@@ -0,0 +1,167 @@
+
+
+
+
+
diff --git a/doc/source/contributor/figures/neutron-metadata-l3-agent.dot b/doc/source/contributor/figures/neutron-metadata-l3-agent.dot
new file mode 100644
index 00000000000..b0e26becf15
--- /dev/null
+++ b/doc/source/contributor/figures/neutron-metadata-l3-agent.dot
@@ -0,0 +1,115 @@
+/*
+neutron-metadata-l3-agent
+
+Edit this file, instead of the corresponding png/svg.
+Those can be re-generated by:
+sudo apt install graphviz
+dot -T svg -o out.svg in.dot
+dot -T png -o out.png in.dot
+*/
+
+digraph {
+
+ compound = true
+ node [
+ shape = record
+ ]
+
+ subgraph cluster_openstack_controller {
+ label = "openstack controller node"
+ nova_metadata [
+ label = "nova metadata service"
+ ]
+ public_openstack_api [
+ label = "public openstack APIs\n(nova, neutron)"
+ ]
+ }
+
+ subgraph cluster_openstack_network {
+ label = "openstack network node"
+ neutron_l3_agent [
+ label = "neutron-l3-agent"
+ ]
+ neutron_metadata_agent [
+ label = "neutron-metadata-agent\n\nadds HTTP headers:\nX-Tenant-ID: project-UUID\nX-Instance-ID: instance-UUID\nX-Instance-ID-Signature: ...\n\nremoves HTTP header:\n X-Neutron-Router-ID"
+ ]
+ subgraph cluster_neutron_router_namespace {
+ label = "neutron router namespace\n(for tenant router)"
+ neutron_l3_ns_metadata_proxy [
+ label = "neutron ns-metadata-proxy\n\nadds HTTP headers:\nX-Forwarded-For: instance-IP\nX-Neutron-Router-ID: router-UUID"
+ ]
+ neutron_iptables [
+ label = "iptables\nnat table, PREROUTING chain\nrule dst=169.254.169.254:80\ntarget REDIRECT to=127.0.0.1:9697"
+ ]
+ neutron_router [
+ label = "neutron router"
+ ]
+ }
+ }
+
+ subgraph cluster_tenant_net_with_gateway {
+ label = "tenant net with gateway"
+ instance [
+ label = "openstack instance\nno 169.254 IP configured locally\nroute: 169.254.169.254 via subnet-gw-IP"
+ ]
+ }
+
+ response_omitted [
+ label = "the response is omitted for brevity..."
+ shape = plaintext
+ ]
+
+ traffic_omitted [
+ label = "omitted..."
+ shape = plaintext
+ ]
+
+ traffic_omitted -> neutron_router [
+ dir = back
+ label = "normal traffic"
+ ]
+
+ neutron_router -> instance [
+ dir = back
+ label = "normal\ntraffic"
+ ]
+
+ neutron_iptables -> instance [
+ label = "HTTP GET\n169.254.169.254:80"
+ dir = back
+ align = left
+ ]
+
+ neutron_l3_ns_metadata_proxy -> neutron_iptables [
+ dir = back
+ label = "metadata\ntraffic"
+ ]
+
+ neutron_metadata_agent -> neutron_l3_ns_metadata_proxy [
+ label = "unix socket"
+ dir = back
+ ]
+
+ neutron_l3_agent -> neutron_router [
+ label = "configures\nroutes"
+ ]
+
+ neutron_l3_agent -> neutron_l3_ns_metadata_proxy [
+ label = "starts"
+ ]
+
+ nova_metadata -> neutron_metadata_agent [
+ dir = back
+ ]
+
+ public_openstack_api -> neutron_metadata_agent [
+ label = "looks up instance UUID"
+ dir = back
+ ]
+
+ nova_metadata -> response_omitted
+ response_omitted -> neutron_metadata_agent [
+ style = invis
+ ]
+
+}
diff --git a/doc/source/contributor/figures/neutron-metadata-l3-agent.png b/doc/source/contributor/figures/neutron-metadata-l3-agent.png
new file mode 100644
index 00000000000..fff4908610e
Binary files /dev/null and b/doc/source/contributor/figures/neutron-metadata-l3-agent.png differ
diff --git a/doc/source/contributor/figures/neutron-metadata-l3-agent.svg b/doc/source/contributor/figures/neutron-metadata-l3-agent.svg
new file mode 100644
index 00000000000..97195bd5e49
--- /dev/null
+++ b/doc/source/contributor/figures/neutron-metadata-l3-agent.svg
@@ -0,0 +1,180 @@
+
+
+
+
+
diff --git a/doc/source/contributor/internals/index.rst b/doc/source/contributor/internals/index.rst
index 52776d6ae6a..74925496114 100644
--- a/doc/source/contributor/internals/index.rst
+++ b/doc/source/contributor/internals/index.rst
@@ -48,6 +48,7 @@ Neutron Internals
linuxbridge_agent
live_migration
local_ips
+ metadata
ml2_ext_manager
network_ip_availability
objects_usage
diff --git a/doc/source/contributor/internals/metadata.rst b/doc/source/contributor/internals/metadata.rst
new file mode 100644
index 00000000000..8b1cf1668d6
--- /dev/null
+++ b/doc/source/contributor/internals/metadata.rst
@@ -0,0 +1,27 @@
+..
+
+=======================================
+Metadata Service Architectural Overview
+=======================================
+
+The following figures give an overview of the traditional implementation of the
+metadata service primarily focusing on the component view and the flow of
+information. There are two distinct figures depicting the metadata service as
+implemented in isolated networks or in networks with a router.
+
+Please be aware that these figures are not complete. They do not apply to
+:ref:`ml2/ovn implementation` or to
+`distributed metadata `_.
+They also omit details like IPv6 metadata or redundancy in the deployment.
+
+Metadata on isolated networks - DHCP Agent
+------------------------------------------
+
+.. image:: ../figures/neutron-metadata-dhcp-agent.png
+ :alt: Overview of traditional metadata architecture with DHCP agent
+
+Metadata on networks with a router - L3 Agent
+---------------------------------------------
+
+.. image:: ../figures/neutron-metadata-l3-agent.png
+ :alt: Overview of traditional metadata architecture with L3 agent