PostgreSQL 19 introduces native property graph support, bringing graph modeling capabilities directly into the relational engine. This feature allows representing vertices (nodes) and edges (relationships) using standard tables while maintaining graph metadata in newly introduced system catalogues.
The five new system catalogues based on property graphs are
- pg_propgraph_element
- pg_propgraph_label
- pg_propgraph_property
- pg_propgraph_element_label
- pg_propgraph_label_property
Each catalogue plays a specific role in mapping relational tables into a graph structure.
We can also use the help command to explore more about the CREATE PROPERTY GRAPH
\h CREATE PROPERTY GRAPH
Output :
Command: CREATE PROPERTY GRAPH
Description: define an SQL-property graph
Syntax:
CREATE [ TEMP | TEMPORARY ] PROPERTY GRAPH name
[ {VERTEX|NODE} TABLES ( vertex_table_definition [, ...] ) ]
[ {EDGE|RELATIONSHIP} TABLES ( edge_table_definition [, ...] ) ]
where vertex_table_definition is:
vertex_table_name [ AS alias ] [ KEY ( column_name [, ...] ) ] [ element_table_label_and_properties ]
and edge_table_definition is:
edge_table_name [ AS alias ] [ KEY ( column_name [, ...] ) ]
SOURCE [ KEY ( column_name [, ...] ) REFERENCES ] source_table [ ( column_name [, ...] ) ]
DESTINATION [ KEY ( column_name [, ...] ) REFERENCES ] dest_table [ ( column_name [, ...] ) ]
[ element_table_label_and_properties ]
and element_table_label_and_properties is either:
NO PROPERTIES | PROPERTIES ALL COLUMNS | PROPERTIES ( { expression [ AS property_name ] } [, ...] )
or:
{ { LABEL label_name | DEFAULT LABEL } [ NO PROPERTIES | PROPERTIES ALL COLUMNS | PROPERTIES ( { expression [ AS property_name ] } [, ...] ) ] } [...]
URL: https://www.postgresql.org/docs/devel/sql-create-property-graph.html
Understanding Property Graphs in PostgreSQL
A property graph consists of:
- Vertices (nodes) - entities like a person
- Edges (relationships) - connections like knows
- Labels - classification (Person, Knows)
- Properties - attributes (name, age, since)
Example Used
CREATE TABLE person (
id int PRIMARY KEY,
name text,
age int
);
CREATE TABLE knows (
src_id int REFERENCES person(id),
dst_id int REFERENCES person(id),
since date
);
CREATE PROPERTY GRAPH social_graph
VERTEX TABLES (
person
KEY (id)
LABEL Person
PROPERTIES (name, age)
)
EDGE TABLES (
knows
KEY (src_id, dst_id)
SOURCE KEY (src_id) REFERENCES person (id)
DESTINATION KEY (dst_id) REFERENCES person (id)
LABEL Knows
PROPERTIES (since)
);
pg_propgraph_element
Stores graph elements, which are either:
- Vertex tables (v)
- Edge tables (e)
Each row represents how a relational table participates in the graph.
Columns and it’s purpose
- oid - Unique identifier of the element
- pgepgid - Graph ID (links to property graph)
- pgerelid - Underlying table OID (person, knows)
- pgealias - Alias used inside graph
- pgekind - 'v' = vertex, 'e' = edge
- pgesrcvertexid - Source vertex (for edges)
- pgedestvertexid - Destination vertex (for edges)
- pgekey - Primary key columns
- pgesrckey - Edge source column
- pgesrcref - Referenced column in vertex
- pgesrceqop - Equality operator
- pgedestkey - Edge destination column
- pgedestref - Referenced column
- pgedesteqop - Equality operator
What It Stores
select * from pg_propgraph_element;
Result :
oid | pgepgid | pgerelid | pgealias | pgekind | pgesrcvertexid | pgedestvertexid | pgekey | pgesrckey | pgesrcref | pgesrceqop | pgedestkey | pgedestref | pgedesteqop
-------+---------+----------+----------+---------+----------------+-----------------+--------+-----------+-----------+------------+------------+------------+-------------
60397 | 60394 | 60373 | person | v | 0 | 0 | {1} | | | | | |
60404 | 60394 | 60381 | knows | e | 60397 | 60397 | {1,2} | {1} | {1} | {96} | {2} | {1} | {96}
(2 rows)
Here, the person table is the vertex and is denoted by v in the column named pgekind, and the table named knows is the edge
- person has only pgekey
- knows contains source and destination mapping
Use Case
- Core mapping between tables and graph structure
- Defines how edges connect vertices
pg_propgraph_label
Stores labels assigned to graph elements.
Each column name and its purpose
- oid - Label id
- pglpid - graph id
- pgllabel - label name
select * from pg_propgraph_label;
Result :
oid | pglpgid | pgllabel
-------+---------+----------
60398 | 60394 | person
60405 | 60394 | knows
(2 rows)
pg_propgraph_property
This catalogue stores property graph’s property related information
Columns and it’s purposes
- oid - Property ID
- pgppgid - Graph ID
- pgpname - Property name
- pgptypid - Data type
- pgptypmod - Type modifier
- pgpcollation - Collation
select * from pg_propgraph_property;
Result :
oid | pgppgid | pgpname | pgptypid | pgptypmod | pgpcollation
-------+---------+---------+----------+-----------+--------------
60400 | 60394 | name | 25 | -1 | 100
60402 | 60394 | age | 23 | -1 | 0
60407 | 60394 | since | 1082 | -1 | 0
(3 rows)
pg_propgraph_element_label
This catalogues is mainly used to maps elements to labels
Columns and their purpose
- oid - Entry ID
- pgellabelid - Label ID
- pgelelid - Element ID
select * from pg_propgraph_element_label;
Result :
oid | pgellabelid | pgelelid
-------+-------------+----------
60399 | 60398 | 60397
60406 | 60405 | 60404
(2 rows)
pg_propgraph_label_property
This catalogue is mainly used to maps labels to propertiesColumns and it’s purpose
- oid - Entry ID
- plppropid - Property ID
- plpellabelid - Label ID
- plpexpr - Expression defining property
What is plpexpr?
- Internal expression (pg_node_tree)
- Represents how column is accessed
Example:
VAR :varattno 2 - name column
VAR :varattno 3 - age column
select * from pg_propgraph_label_property;
Result :
oid | plppropid | plpellabelid | plpexpr
-------+-----------+--------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------
60401 | 60400 | 60399 | {VAR :varno 1 :varattno 2 :vartype 25 :vartypmod -1 :varcollid 100 :varnullingrels (b) :varlevelsup 0 :varreturningtype 0 :varnosyn 1 :varattnosyn 2 :location -1}
60403 | 60402 | 60399 | {VAR :varno 1 :varattno 3 :vartype 23 :vartypmod -1 :varcollid 0 :varnullingrels (b) :varlevelsup 0 :varreturningtype 0 :varnosyn 1 :varattnosyn 3 :location -1}
60408 | 60407 | 60406 | {VAR :varno 1 :varattno 3 :vartype 1082 :vartypmod -1 :varcollid 0 :varnullingrels (b) :varlevelsup 0 :varreturningtype 0 :varnosyn 1 :varattnosyn 3 :location -1}
(3 rows)
The introduction of property graph support in PostgreSQL 19 marks a meaningful shift in how complex relationships can be modeled within a purely relational system. Instead of introducing a separate graph engine, PostgreSQL integrates graph capabilities through a well-structured set of system catalogues. The five catalogues named pg_propgraph_element, pg_propgraph_label, pg_propgraph_property, pg_propgraph_element_label, and pg_propgraph_label_property are work together to describe every aspect of a graph, from its structural components to its semantic meaning.
What makes this approach notable is its reliance on metadata rather than new storage mechanisms. Existing tables remain unchanged, while the graph abstraction is built as an additional layer. The CREATE PROPERTY GRAPH command acts as the entry point, translating familiar relational schemas into graph representations by registering elements, labels, and properties across these catalogues. Each catalogue has a focused responsibility, and together they form a cohesive system that enables PostgreSQL to interpret relational data as a connected graph.
This design keeps PostgreSQL aligned with its core philosophy: extensibility without sacrificing stability. Developers can continue using standard tables while gaining the ability to model and query relationships in a more expressive way. As this feature evolves, it opens the door for advanced use cases such as network analysis, recommendation systems, and graph-based querying, all within the PostgreSQL ecosystem.
In essence, PostgreSQL 19 does not replace the relational model but enhances it, allowing graphs to exist alongside tables through a carefully designed catalog-driven architecture.