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.
In this section
- EntitiesEvery node label in WhisperGraph — what it represents, its count, and the queryable properties on threat-listed indicators, prefixes, ASNs, and ROAs.
- Connection TypesEvery edge type in WhisperGraph — direction, source and target labels, and the physical-vs-virtual rules that decide how you traverse it.
- Pivoting ExamplesWorked cross-layer traversals — from a domain to the network that routes it, an IP to its jurisdiction, an ASN to its registry entity and BGP neighbours, an actor to its techniques. Examples, not an exhaustive list.
On this page (4)
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 hostname 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 census the graph holds 41 node labels and 52 edge types, across 7.5B nodes and 39.6B edges.
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, Certificate Transparency observations | HOSTNAME, TLD, CT_OBSERVATION |
| Addressing | IPv4/IPv6 addresses and the CIDR prefixes they sit in | IPV4, IPV6, PREFIX |
| Network / routing | Autonomous systems, BGP announcements and observed AS paths, adjacency, MOAS conflicts, RPKI | ASN, ANNOUNCED_PREFIX, BGP_PATH_OBSERVATION, ROA |
| Ownership / WHOIS | Registrants, registrars, contact email and phone, and RDAP registration entities for prefixes and ASNs | ORGANIZATION, REGISTRAR, EMAIL, PHONE, RDAP_ENTITY |
| Geo | GeoIP city and country | CITY, COUNTRY |
| Email security | SPF, DMARC, DKIM | HOSTNAME, DMARC_RECIPIENT, VENDOR |
| Physical infrastructure | Data centers, IXPs, submarine cables, CDN PoPs, cloud regions (partial) | FACILITY, INTERNET_EXCHANGE, SUBMARINE_CABLE, CDN_POP, CLOUD_REGION |
| Threat intelligence | Feeds, categories, signals, Tor relays, TLS fingerprints (partial), phishing-kit URL paths | FEED_SOURCE, CATEGORY, THREAT_SIGNAL_TYPE, TOR_RELAY, TLS_FINGERPRINT, URL |
| Threat actors | Named actors and the MITRE ATT&CK techniques they use | ACTOR, ATTACK_PATTERN, THREAT_TAG |
Most node labels carry an indexed name, and anchoring on {name: "value"} is the difference between an instant lookup and a full-graph scan. ROA does not — identify a ROA by its prefix and asn. ORGANIZATION is reached through an edge, not guessed by name. Its names are raw registrant strings, so one company appears under several spellings; traverse REGISTERED_BY from a hostname or ASN and fold with SAME_ORG_AS to the canonical record.
Not every layer is equally populated, and the partial ones are marked (partial) above. Three labels are node-only — DNS_ROOT_INSTANCE, DWI_DOMAIN and RIR carry no edge of any type, so no traversal reaches them. On any thin plane, a zero-row result means Whisper holds no observation — never that the host has none. Entities gives the per-label counts.
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 next
The three references that break the schema apart are listed at the top of this
section. For the procedures that wrap common multi-step logic into a single
CALL, see Procedures; for the query language
itself, the Cypher.
Check the live schema
The db.* introspection procedures return the live label and edge sets, and they are cheap — they read the declared store rather than expanding the graph, so they answer immediately:
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'). Confirm a label against db.labels() before you build on a hint: TAGGED_AS declares CERTIFICATE among its source labels, and db.labels() returns no such label. |
GET /api/query/stats (see the API Reference) returns the live node and edge totals in one cheap call.