Building a knowledge graph means deciding which questions it has to answer, choosing a data model, defining or reusing an ontology, extracting entities and relationships from source data, reconciling those entities against stable identifiers, loading the result into a store, then querying, validating and maintaining it. The order matters: most failed graphs were modeled before anyone wrote down what they were for. This page walks the full pipeline with a running example and links to the pages that cover each step in depth.
The running example is small and concrete: a graph of a university’s academic staff, the departments they belong to, the courses they teach and the papers they publish. It is the kind of graph an institution actually builds, and every step below refers back to it.
Step 1: Scope the graph with competency questions
A competency question is a question the finished graph must be able to answer. Written before any modeling, competency questions determine which entity types exist, which relationships are needed, and which data sources have to be brought in. Written afterward, they become a test suite.
For the university example:
- Which faculty members in the College of Engineering have published with a co-author outside the university in the past three years?
- Which courses are taught by staff who hold a doctorate from a different institution?
- If a named professor leaves, which courses lose their only qualified instructor?
Each question implies structure. The first requires a Person type, an Organization type, a Publication type, an authorship relationship, an affiliation relationship and a date on the publication. The third requires a qualification relationship between people and courses that does not exist in any timetable system, which is exactly the sort of gap this exercise surfaces early.
Two rules keep the list useful. Every question must be answerable from data that can actually be obtained, and every question must be one somebody wants answered. A graph scoped to “all knowledge about the university” has no completion criterion and no test.
Step 2: Choose a data model
Two models dominate. RDF represents everything as triples of subject, predicate and object, with globally unique IRIs as identifiers, queried with SPARQL. A labeled property graph (LPG) represents data as nodes and relationships that both carry key-value properties, queried with Cypher or Gremlin. The full comparison lives at /concepts/property-graph-vs-rdf/, and the store-level consequences at /build/graph-databases/.
The choice matters in a narrow set of cases. RDF is the stronger option when data has to merge with graphs published by other organizations, when identifiers must be dereferenceable, when formal semantics and reasoning are needed, or when the output feeds structured data on a website. An LPG is the stronger option when the graph is internal, when relationships need their own attributes (a co-authorship edge with a paper count and a first-collaboration date), and when the team is already comfortable with Cypher.
Where the choice does not matter much: analytics on the graph structure itself. Centrality, path finding and community detection work the same on both, and both export to a format the other can read. Teams that hesitate for weeks over this decision usually lose more time than either model would have cost them.
The university example uses RDF, because publication data has to reconcile against external identifiers and because the same graph will later drive schema.org markup on staff profile pages.
Step 3: Design or reuse an ontology
The ontology names the types and properties the graph is allowed to use. Reuse beats invention: schema.org covers people, organizations, courses and creative works well enough for most public-facing graphs, and academic domains have established vocabularies. Full treatment at /concepts/ontologies/ and, for the formal language, /languages/owl/.
A first pass for the example, in Turtle:
@prefix ex: <https://example.edu/kg/> .
@prefix schema: <https://schema.org/> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix owl: <http://www.w3.org/2002/07/owl#> .
ex:FacultyMember a owl:Class ;
rdfs:subClassOf schema:Person ;
rdfs:label "Faculty member"@en .
ex:teaches a owl:ObjectProperty ;
rdfs:domain ex:FacultyMember ;
rdfs:range schema:Course ;
rdfs:label "teaches"@en .
Three habits prevent most later pain. Keep the number of classes small at the start, because every class is a decision that has to be applied consistently across millions of rows. Give every property an explicit domain and range even if nothing enforces them, since the declaration documents intent. And separate the ontology file from the instance data, so the model can be versioned and reviewed on its own.
Step 4: Extract entities and relationships
Sources fall into three groups, and each takes a different approach.
Structured sources (a student records database, an HR system, a CSV of course listings) are the cheapest and should be handled first. The work is mapping: each row becomes a node, each foreign key becomes an edge, each column becomes a property or is dropped. R2RML is the W3C standard for expressing relational-to-RDF mappings, and most triple stores ship a loader for tabular data.
Semi-structured sources (JSON APIs, XML feeds, existing schema.org markup on pages) need field-by-field mapping but no language processing.
Unstructured text (staff biographies, paper abstracts, policy documents) needs named entity recognition to find the mentions, relation extraction to find what connects them, and entity linking to resolve each mention to an identifier. That pipeline is covered at /concepts/entity-linking-ner-and-extraction/, and worked end to end in Python, including where a language model helps and where it does not, at /build/knowledge-graph-python/.
The output of extraction is candidate triples, not graph content. Treated as candidates, they can be scored, sampled and reviewed. Written straight into the store, they are indistinguishable from curated facts within a week.
Step 5: Reconcile and deduplicate
Extraction produces “J. Smith”, “John Smith” and “Smith, John A.” as three entities. Reconciliation decides they are one, and gives that one a stable identifier.
Internal identifiers come first: an employee number, an ORCID for a researcher, an ISBN for a book, a database primary key. External identifiers come second, and they are what makes a graph interoperable. Linking a person to their Wikidata item (/ecosystems/wikidata/) or a department to its ROR record means later data can join on that identifier rather than on a name.
In RDF this is expressed with owl:sameAs or schema:sameAs:
@prefix ex: <https://example.edu/kg/> .
@prefix schema: <https://schema.org/> .
ex:person-44120 schema:sameAs
<https://orcid.org/0000-0002-1825-0097> ,
<http://www.wikidata.org/entity/Q7186> .
Matching strategy in practice is a cascade. Exact match on a strong identifier resolves most records. Blocking (compare only records that share a surname prefix or a department) makes the remaining comparison tractable. String similarity plus contextual evidence (same co-authors, same institution, overlapping dates) scores the pairs. A human reviews the middle band, where the score is neither clearly a match nor clearly not. Full automation of that middle band is where duplicate and merged-person errors come from, and merged-person errors are far more expensive to undo than duplicates.
Step 6: Load into a store
The store choice follows the data model. RDF goes into a triple store such as Apache Jena Fuseki, GraphDB, Stardog or Blazegraph; an LPG goes into Neo4j, Memgraph or a similar engine. Options and categories are surveyed at /build/knowledge-graph-tools/, and the architectural differences at /build/graph-databases/.
Load in bulk, not row by row. Every serious store has a bulk import path that bypasses transactional overhead, and the difference from a loop of individual inserts is orders of magnitude on any real dataset. Load into named graphs (RDF) or label them by source (LPG) so that a bad source can be dropped and reloaded without touching the rest.
Keep the load reproducible. A build that runs from raw sources to a loaded store in one command can be re-run after an ontology change; one that depends on manual steps cannot, and will quietly diverge from its sources.
Step 7: Query and validate
The competency questions from step 1 come back as queries. If they run and return sensible results, the graph is doing its job.
PREFIX ex: <https://example.edu/kg/>
PREFIX schema: <https://schema.org/>
PREFIX rdfs: <http://www.w3.org/2000/01/rdf-schema#>
SELECT ?facultyLabel (COUNT(DISTINCT ?course) AS ?courses)
WHERE {
?faculty a ex:FacultyMember ;
rdfs:label ?facultyLabel ;
ex:teaches ?course .
}
GROUP BY ?facultyLabel
HAVING (COUNT(DISTINCT ?course) > 3)
ORDER BY DESC(?courses)
The query language itself is covered at /languages/sparql/, and the triple model it matches at /concepts/triples-subject-predicate-object/.
Validation is a separate concern from querying. SHACL describes the shapes data must conform to and reports every node that violates them, which is what turns “the graph looks fine” into a pass or fail in a build pipeline:
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix ex: <https://example.edu/kg/> .
@prefix schema: <https://schema.org/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ex:FacultyShape a sh:NodeShape ;
sh:targetClass ex:FacultyMember ;
sh:property [
sh:path schema:name ;
sh:minCount 1 ;
sh:datatype xsd:string ;
] ;
sh:property [
sh:path schema:memberOf ;
sh:minCount 1 ;
sh:nodeKind sh:IRI ;
] .
That shape says a faculty member needs exactly one name and at least one department, and that the department must be an IRI rather than a bare string. See /languages/shacl/. Run the shapes on every load, and treat violations like failing unit tests.
Beyond shape validation, three checks catch most quality problems: count entities by type and compare against the source system, look for orphan nodes with no edges, and sample fifty random entities and read them. The last one finds errors no automated check catches. Visual inspection helps here, and the tools for it are at /build/knowledge-graph-visualization/.
Step 8: Maintain, with provenance and time
A knowledge graph that isn’t maintained decays faster than a relational database, because its value comes from connections, and a stale connection is worse than a missing one.
Record provenance on everything. Every fact should carry where it came from and when it was asserted. In RDF, the common patterns are named graphs (one graph per source, so provenance attaches to the graph) and PROV-O properties on a statement:
@prefix ex: <https://example.edu/kg/> .
@prefix prov: <http://www.w3.org/ns/prov#> .
@prefix dcterms: <http://purl.org/dc/terms/> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
ex:graph-hr-2026-09 a prov:Entity ;
prov:wasDerivedFrom <https://example.edu/systems/hr> ;
dcterms:created "2026-09-10T04:00:00Z"^^xsd:dateTime ;
dcterms:publisher ex:registry .
Provenance is what makes a correction possible. Without it, a wrong fact can be deleted but its source keeps re-inserting it on the next load.
Model change explicitly where it matters. A person’s department is not a fact; it is a fact with a validity period. RDF handles this with reification, named graphs, or n-ary relation nodes; an LPG handles it with properties on the relationship. Either way, you have to decide how to model time before the first load, because retrofitting it means rewriting every affected edge.
Re-run the competency questions on a schedule. They are the regression tests. A question that used to return twelve rows and now returns none usually means an upstream source changed shape, not that reality changed.
Version the ontology separately from the data. Adding a class is safe. Renaming a property, narrowing a range, or merging two classes breaks queries written against the old model, and those queries live in dashboards and applications outside the graph team’s view.
For developers
Build the thinnest end-to-end slice first: one source, three entity types, one competency question, loaded and queried. A working pipeline with ten thousand triples teaches more about modeling decisions than a design document does, and it exposes the reconciliation problems that drive real cost. Only then widen the sources. Keep the whole build in version control, including ontology, mappings, SHACL shapes and the query test suite, and make the load idempotent so it can be run repeatedly against a clean store.
For SEOs
The same pipeline produces a graph that drives structured data. An internal graph of organizations, people, products and content, reconciled against Wikidata and official profile URLs, is the correct source for sameAs values and for consistent Organization and Person markup across a site. Generating markup from a graph rather than page by page eliminates the contradictions between templates that make an entity harder for a search engine to resolve. The markup side is covered at /ecosystems/structured-data/ and /seo/sameas-schema/.
Where each step is covered in depth
- Data model choice and stores: /build/graph-databases/
- Tools by category: /build/knowledge-graph-tools/
- Extraction and modeling in Python: /build/knowledge-graph-python/
- Retrieval over a finished graph: /build/graphrag/
- Inspecting the result: /build/knowledge-graph-visualization/
Related pages
- What is a knowledge graph
- Build a knowledge graph in Python
- Graph databases for knowledge graphs
- Knowledge graph tools
- Ontologies
- RDF
FAQ
How do you build a knowledge graph from scratch?
Start with competency questions the graph must answer, then choose between RDF and a labeled property graph, define or reuse an ontology, extract entities and relationships from structured and unstructured sources, reconcile those entities against stable identifiers, load into a triple store or graph database, and validate with SHACL and the original questions. Maintenance with provenance follows.
How long does it take to build a knowledge graph?
A working first slice covering one source and a handful of entity types takes days. The time goes into entity reconciliation, source integration, and ongoing maintenance rather than into modeling or loading. Scope by competency question rather than by data volume, and ship a narrow graph that answers three questions before widening it.
Do you need a graph database to build a knowledge graph?
No. A knowledge graph is a data model, not a product. Small graphs run happily in an RDF file loaded with rdflib, in SQLite, or in memory. A graph database or triple store becomes worthwhile when the graph exceeds memory, when multiple applications query it concurrently, or when traversals of several hops need to be fast.
What is the hardest part of building a knowledge graph?
Entity resolution. Deciding that three differently spelled names refer to one person, and doing it consistently across millions of records and repeated loads, costs more than modeling, extraction, and loading combined. Merged-entity errors are worse than duplicates, because a duplicate can be merged later while a wrong merge is hard to detect and hard to undo.
Sources and further reading
- Hogan et al., Knowledge Graphs (open access book): https://kgbook.org/
- Stanford CS520, How to Create a Knowledge Graph: https://web.stanford.edu/class/cs520/2020/notes/How_To_Create_A_Knowledge_Graph.html
- W3C, RDF 1.1 Primer: https://www.w3.org/TR/rdf11-primer/
- W3C, Shapes Constraint Language (SHACL): https://www.w3.org/TR/shacl/
- W3C, R2RML: RDB to RDF Mapping Language: https://www.w3.org/TR/r2rml/
- W3C, PROV-O: The PROV Ontology: https://www.w3.org/TR/prov-o/
