Graph Schema
How WhisperGraph is structured: the internet modeled as one connected graph, joined layer to layer. Start here, then drill into entities, connections, and pivots.
Graph Schema Documentation
WhisperGraph models the internet as one connected graph — every layer joined to the next, so a single query can walk from a web link to the physical building that routes it. This page is the map: the layers, how they connect, and where to go for the full reference. As of the latest sync the graph holds 39 node labels and 46 edge types, across ~7.4 billion nodes and ~39 billion edges.
The WhisperGraph schema — node labels and edge types pre-joined into one graph (a curated core of the model).
The layers
The graph is organized into layers, each a cluster of related entity types. The point of a pre-joined graph is that these layers are linked — you traverse across them in one query, not through separate lookups.
| Layer | What it holds | Core entities |
|---|---|---|
| Naming / DNS | Hostnames, the domain hierarchy, resolution, CNAME/NS/MX | HOSTNAME, TLD |
| Addressing | IPv4/IPv6 addresses and the CIDR prefixes they sit in | IPV4, IPV6, PREFIX |
| Network / routing | Autonomous systems, BGP announcements, peering, RPKI | ASN, ANNOUNCED_PREFIX, ROA |
| Ownership / WHOIS | Registrants, registrars, contact email and phone | ORGANIZATION, REGISTRAR, EMAIL, PHONE |
| Geo | GeoIP city and country | CITY, COUNTRY |
| Email security | SPF, DMARC, DKIM, TLS fingerprints | HOSTNAME, DMARC_RECIPIENT, TLS_FINGERPRINT |
| Physical infrastructure | Data centers, IXPs, submarine cables, CDN PoPs, cloud regions | FACILITY, INTERNET_EXCHANGE, SUBMARINE_CABLE, CDN_POP, CLOUD_REGION |
| Threat intelligence | Feeds, categories, signals, Tor relays | FEED_SOURCE, CATEGORY, THREAT_SIGNAL_TYPE, TOR_RELAY |
| Threat actors | Named actors and the MITRE ATT&CK techniques they use | ACTOR, ATTACK_PATTERN, THREAT_TAG |
Every node carries a name property, and {name: "value"} lookups are indexed — anchoring on a name is the difference between an instant O(1) lookup and a full-graph scan.
How the layers connect
A hostname resolves down to an address, the address sits in a routed prefix, the prefix is announced by an autonomous system, and that system is physically present in a facility. Read top to bottom, that is a single traversal across four layers:
MATCH (h:HOSTNAME {name: "github.com"})-[:RESOLVES_TO]->(ip:IPV4)
-[:ANNOUNCED_BY]->(ap:ANNOUNCED_PREFIX)-[:ROUTES]->(a:ASN)-[:HAS_NAME]->(n:ASN_NAME)
RETURN ip.name, ap.name, a.name, n.name LIMIT 5
That chain — and the dozens of others the graph supports — is what a flat lookup API cannot answer. The Pivoting Examples page collects the ones you will reach for most.
Where to go next
This section breaks the schema into three references:
- Entities — every node label, what it represents, its counts, and the queryable properties (threat verdicts, BGP flags, RPKI fields).
- Connection Types — every edge type, its direction, source and target labels, and the physical-vs-virtual rules that decide how you traverse it.
- Pivoting Examples — the cross-layer chains, each with the traversal it encodes and a runnable query.
For the procedures that wrap common multi-step logic into a single CALL, see Procedures. For the query language itself, see the Cypher Reference.
Check the live schema
The counts on these pages are a snapshot and drift with each refresh. The db.* introspection procedures return the live label and edge sets, and never count against your quota:
CALL db.labels() YIELD label RETURN label ORDER BY label LIMIT 12
| Call | Returns |
|---|---|
CALL db.labels() | Every node label with its count. |
CALL db.relationshipTypes() | Every edge type with its source and target labels. |
CALL db.propertyKeys() | Every property name in use. |
CALL db.schema() | A structured overview of the whole graph, including traversalHints for virtual edges. Accepts a format argument ('json', 'markdown', or 'details'). |
GET /api/query/stats (see the API Reference) returns the live node and edge totals in one cheap call.