{
  "source_file": "0930",
  "source_platform": "Dev.to",
  "author": "Tae Kim",
  "title_listed": "Temporal Edges in Knowledge Graphs: Why Static Edges Break Graph RAG",
  "keywords": "",
  "domain": "大模型算法",
  "content_type": "深度技术解析",
  "is_paid_flag": "否",
  "url": "https://dev.to/hannune/temporal-edges-in-knowledge-graphs-why-static-edges-break-graph-rag-1ll",
  "publish_date": "2026-07-15",
  "corpus_stage": "",
  "notes": "",
  "id": "20db340ed146",
  "collected_at": "2026-10-02T14:04:08",
  "title": "Temporal Edges in Knowledge Graphs: Why Static Edges Break Graph RAG - DEV Community",
  "body_markdown": "Standard knowledge graph edges are timeless by default. When you insert \"Company X → CEO → Person A,\" there is no expiration date on that relationship. The graph becomes stale the moment the CEO changes, but it does not know it is stale.\nI ran into this building a multilingual knowledge graph for East Asian corporate data at\n2asy.ai\n. Corporate structures change constantly — leadership transitions, subsidiary changes, regulatory status updates — and every change makes some existing edges incorrect rather than just outdated.\nThe Problem with Static Edges\nHere is what a static edge insertion looks like:\n# Static edge — no temporal metadata\ngraph\n.\nadd_edge\n(\nsource\n=\n\"\nsamsung-electronics\n\"\n,\nrelation\n=\n\"\nCEO\n\"\n,\ntarget\n=\n\"\nlee-jae-yong\n\"\n,\n)\nEnter fullscreen mode\nExit fullscreen mode\nWhen the CEO changes, you either:\nDelete the old edge and insert a new one (losing history)\nInsert a new edge without removing the old one (getting conflicting answers)\nNeither is acceptable when you need the graph to answer both current and historical queries correctly.\nThe Fix: (valid_from, valid_to) on Every Edge\nEvery relationship gets temporal properties as first-class fields:\n# Temporal edge\ngraph\n.\nadd_edge\n(\nsource\n=\n\"\nsamsung-electronics\n\"\n,\nrelation\n=\n\"\nCEO\n\"\n,\ntarget\n=\n\"\nlee-jae-yong\n\"\n,\nvalid_from\n=\n\"\n2022-10-27\n\"\n,\nvalid_to\n=\nNone\n,\n# None = currently active\n)\nEnter fullscreen mode\nExit fullscreen mode\nWhen an event modifies an existing relationship, the old edge gets a closed\nvalid_to\ndate rather than being deleted:\ndef\nsupersede_ceo\n(\ncompany_id\n:\nstr\n,\nnew_ceo_id\n:\nstr\n,\neffective_date\n:\nstr\n):\ncurrent\n=\ngraph\n.\nfind_edge\n(\nsource\n=\ncompany_id\n,\nrelation\n=\n\"\nCEO\n\"\n,\nvalid_to\n=\nNone\n)\nif\ncurrent\n:\ngraph\n.\nupdate_edge\n(\ncurrent\n.\nid\n,\nvalid_to\n=\neffective_date\n)\ngraph\n.\nadd_edge\n(\nsource\n=\ncompany_id\n,\nrelation\n=\n\"\nCEO\n\"\n,\ntarget\n=\nnew_ceo_id\n,\nvalid_from\n=\neffective_date\n,\nvalid_to\n=\nNone\n,\n)\nEnter fullscreen mode\nExit fullscreen mode\nGraph traversal queries default to as-of the current date unless the caller explicitly requests full history.\nThe Hard Part: Supersession Logic\nThe tricky design decision is distinguishing which edge types supersede and which accumulate.\nA CEO appointment is one-to-one: the new edge invalidates the old one. A subsidiary relationship is many-to-many: a company can have multiple subsidiaries simultaneously, so the new edge extends rather than replaces.\nThis distinction has to live in the\nedge schema\n, not in the insertion code.\nEDGE_CARDINALITY\n=\n{\n\"\nCEO\n\"\n:\n\"\none_to_one\n\"\n,\n\"\nCFO\n\"\n:\n\"\none_to_one\n\"\n,\n\"\nSUBSIDIARY\n\"\n:\n\"\nmany_to_many\n\"\n,\n\"\nBOARD_MEMBER\n\"\n:\n\"\nmany_to_many\n\"\n,\n}\nEnter fullscreen mode\nExit fullscreen mode\nIf it lives in insertion code, every developer who writes an insertion path has to know the business rules. If it lives in the schema, the graph enforces it automatically.\nFor East Asian corporate data, I had to map over 40 relationship types to cardinality rules. The initial list took two days; maintaining it as new event types were discovered was ongoing work.\nGraph RAG Implications at Retrieval Time\nA query for \"Samsung's leadership structure in Q3 2024\" needs to traverse edges that were valid during that specific window:\ndef\nquery_as_of\n(\nstart_node_id\n:\nstr\n,\nrelation\n:\nstr\n,\nas_of_date\n:\nstr\n):\nreturn\ngraph\n.\nfind_edges\n(\nsource\n=\nstart_node_id\n,\nrelation\n=\nrelation\n,\nfilters\n=\n{\n\"\nvalid_from\n\"\n:\n{\n\"\nlte\n\"\n:\nas_of_date\n},\n\"\nvalid_to\n\"\n:\n{\n\"\ngte\n\"\n:\nas_of_date\n,\n\"\nor_null\n\"\n:\nTrue\n}\n}\n)\nEnter fullscreen mode\nExit fullscreen mode\nWithout temporal modeling, the graph returns the current structure and nothing in the response signals that it is answering a different question than the one asked.\nWhy Test Sets Hide This Problem\nThe retrieval accuracy difference between a temporally-modeled graph and a static graph is not visible on test sets built from current data. It shows up the first time a user asks a historical question and the system answers confidently with the wrong year's data.\nStandard RAG evaluation benchmarks almost always test against current-state questions. If your knowledge domain has history that matters — corporate actions, regulatory changes, personnel movements — you have to build your own eval set with historical queries and known-correct answers at specific timestamps.\nI built ours from public Korean corporate disclosure data, which has machine-readable effective dates on most events. That gave us a dataset where we knew what the correct graph state was at any given quarter. The temporal modeling errors were the largest single category before we added\n(valid_from, valid_to)\nto the schema.\nWorking on multilingual knowledge graphs and Graph RAG pipelines at\n2asy.ai\n. More writing at\nhannune.ai\n.\nCover:\nPlanet Volumes\non\nUnsplash",
  "metadata": {
    "title": "Temporal Edges in Knowledge Graphs: Why Static Edges Break Graph RAG - DEV Community",
    "description": "Standard knowledge graph edges are timeless by default. When you insert \"Company X → CEO → Person A,\"... Tagged with graphrag, knowledgegraph, graphs, python.",
    "keywords": "graphrag, knowledgegraph, graphs, python, software, coding, development, engineering, inclusive, community",
    "author": null,
    "og:type": "article",
    "og:url": "https://dev.to/hannune/temporal-edges-in-knowledge-graphs-why-static-edges-break-graph-rag-1ll",
    "og:title": "Temporal Edges in Knowledge Graphs: Why Static Edges Break Graph RAG",
    "og:description": "Standard knowledge graph edges are timeless by default. When you insert \"Company X → CEO → Person A,\"...",
    "og:site_name": "DEV Community",
    "og:image": "https://media2.dev.to/dynamic/image/width=1200,height=627,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1737505599162-d9932323a889%3Fw%3D1200%26h%3D630%26fit%3Dcrop%26auto%3Dformat%26q%3D80%26fm%3Djpg",
    "twitter:site": "@thepracticaldev",
    "twitter:creator": "@HannuneTech",
    "twitter:title": "Temporal Edges in Knowledge Graphs: Why Static Edges Break Graph RAG",
    "twitter:description": "Standard knowledge graph edges are timeless by default. When you insert \"Company X → CEO → Person A,\"...",
    "twitter:card": "summary_large_image",
    "twitter:widgets:new-embed-design": "on",
    "twitter:image:src": "https://media2.dev.to/dynamic/image/width=1200,height=627,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fimages.unsplash.com%2Fphoto-1737505599162-d9932323a889%3Fw%3D1200%26h%3D630%26fit%3Dcrop%26auto%3Dformat%26q%3D80%26fm%3Djpg"
  },
  "paywall": {
    "listed_paid": false,
    "detected": false,
    "marker": "",
    "public_only": false,
    "policy": "付费/会员内容只保留页面公开可见部分，不绕过付费墙"
  },
  "crawl": {
    "success": true,
    "status_code": 200,
    "error": ""
  },
  "code_blocks": [
    {
      "file": "attachments/20db340ed146/code/body-000.txt",
      "chars": 136,
      "language": "text"
    },
    {
      "file": "attachments/20db340ed146/code/body-001.txt",
      "chars": 190,
      "language": "text"
    },
    {
      "file": "attachments/20db340ed146/code/body-002.txt",
      "chars": 426,
      "language": "text"
    },
    {
      "file": "attachments/20db340ed146/code/body-003.txt",
      "chars": 143,
      "language": "text"
    },
    {
      "file": "attachments/20db340ed146/code/body-004.txt",
      "chars": 297,
      "language": "text"
    }
  ],
  "images": [],
  "audio": [],
  "videos": [],
  "links": [
    {
      "href": "https://2asy.ai/",
      "label": "2asy.ai",
      "type": "a"
    },
    {
      "href": "https://hannune.ai/",
      "label": "hannune.ai",
      "type": "a"
    },
    {
      "href": "https://unsplash.com/@planetvolumes",
      "label": "Planet Volumes",
      "type": "a"
    },
    {
      "href": "https://unsplash.com/",
      "label": "Unsplash",
      "type": "a"
    }
  ],
  "repair_version": 2,
  "repaired_at": "2026-10-14T10:49:42Z",
  "source_url": "https://dev.to/hannune/temporal-edges-in-knowledge-graphs-why-static-edges-break-graph-rag-1ll",
  "papers": [],
  "actual_video_files": [],
  "body_chars": 4772,
  "expected_body_images": 0,
  "discovery_status": "ok",
  "delivery_status": "ok",
  "missing_reason": "",
  "raw_html": "attachments/20db340ed146/pages/source.html",
  "local_html": "attachments/20db340ed146/pages/article.html",
  "body_base_path": "attachments/20db340ed146/pages/",
  "body_markdown_path": "attachments/20db340ed146/pages/article.md"
}