Skip to content

Conversation

@jpabbuehl
Copy link

@jpabbuehl jpabbuehl commented Dec 23, 2025

Summary

Add support for Apache AGE (A Graph Extension), bringing graph database capabilities and the Cypher query language to PGlite.

What is AGE?

Apache AGE is a PostgreSQL extension that adds:

  • Graph data model: Nodes (vertices) and relationships (edges)
  • Cypher query language: Industry-standard graph query language
  • Hybrid queries: Combine SQL and Cypher in the same database

Usage

import { PGlite } from '@electric-sql/pglite'
import { age } from '@electric-sql/pglite/age'
const pg = new PGlite({ extensions: { age } })
// Create a graph
await pg.exec("SELECT ag_catalog.create_graph('social');")
// Create nodes and relationships
await pg.exec( SELECT * FROM ag_catalog.cypher('social', $$ CREATE (alice:Person {name: 'Alice'})-[:KNOWS]->(bob:Person {name: 'Bob'}) RETURN alice, bob $$) as (alice ag_catalog.agtype, bob ag_catalog.agtype); )
// Query the graph
const result = await pg.query( SELECT * FROM ag_catalog.cypher('social', $$ MATCH (p:Person)-[:KNOWS]->(friend:Person) RETURN p.name, friend.name $$) as (person ag_catalog.agtype, friend ag_catalog.agtype); )

Changes

New Files

File Description
packages/pglite/src/age/index.ts Extension wrapper with initialization
packages/pglite/tests/age.test.ts Comprehensive test suite (34 tests)
docs/extensions/age.md User documentation with examples

Modified Files

File Change
packages/pglite/package.json Add ./age export
packages/pglite/tsup.config.ts Add src/age/index.ts entry point
packages/pglite/scripts/bundle-wasm.ts Add age path replacement

Technical Details

Extension Initialization

The wrapper handles:

  1. CREATE EXTENSION IF NOT EXISTS age
  2. LOAD 'age' (activates Cypher parser hooks)
  3. SET search_path (includes ag_catalog for operator class resolution)
  4. Hook verification (ensures Cypher parsing works)

32-bit WASM Compatibility

AGE required patches for PGlite's 32-bit WASM environment. The postgres-pglite PR includes AGE as a submodule from a fork with a Makefile-only patch that strips PASSEDBYVALUE from the graphid type at build time when SIZEOF_DATUM=4 is passed.

Documentation

Full documentation added at docs/extensions/age.md:

  • Installation and setup
  • Quick start guide
  • Complete social network example
  • Cypher syntax reference
  • Known limitations

Limitations

  • load_labels_from_file() not available (no filesystem in WASM)
  • Large graphs may hit WASM memory limits
  • CPU-intensive for complex graph traversals

Related PRs

Checklist

  • TypeScript compiles without errors
  • All 34 tests pass (pnpm test)
  • ESM and CJS builds work
  • Documentation added
  • Package exports configured
  • Browser testing (pnpm test:web)

Add support for Apache AGE (A Graph Extension) which brings graph
database capabilities and the Cypher query language to PGlite.

Features:
- Full Cypher query language support
- Create/query/update/delete graph nodes and relationships
- Variable-length path queries
- Integration with standard SQL

New files:
- packages/pglite/src/age/index.ts - Extension wrapper
- packages/pglite/tests/age.test.ts - Test suite (43 tests)
- docs/extensions/age.md - User documentation

Modified files:
- package.json - Add ./age export
- tsup.config.ts - Add entry point
- bundle-wasm.ts - Add path replacement

Usage:
  import { PGlite } from '@electric-sql/pglite'
  import { age } from '@electric-sql/pglite/age'

  const pg = new PGlite({ extensions: { age } })
  await pg.exec("SELECT ag_catalog.create_graph('my_graph');")

Requires: electric-sql/postgres-pglite PR for build system changes
Depends on: apache/age 32-bit compatibility (jpabbuehl/age fork)
@tdrz
Copy link
Collaborator

tdrz commented Dec 23, 2025

@jpabbuehl Thank you for this! We are having a bit of time off atm, but we'll have a look at this as soon as we're back.

I know it's a lot to ask, but would it be possible to upstream your changes for 32bit support to the official AGE repo?

@tdrz tdrz self-requested a review December 23, 2025 19:10
@jpabbuehl
Copy link
Author

apache/age#2286

Here it is.

@tdrz
Copy link
Collaborator

tdrz commented Jan 6, 2026

@jpabbuehl We really like this but we are not quite ready to link to individual's repos. It would be great to have that PR merged on the Apache repo. Will comment there as well.

One other option would be for us to make a fork of the main repo and apply your changes there. The issue with this approach is that we'll be left maintaining it and we are tight on resources...

- Update submodule to include SIZEOF_DATUM=4 build flag for AGE
- Minor code style fixes (quote consistency)
@jpabbuehl
Copy link
Author

@tdrz updated to latest Apache Age PR. let's wait and see how it goes upstream :)

@jpabbuehl
Copy link
Author

@tdrz merged upstream. I've updated this PR and the other for Build with the Parameter 32bit. Happy to hear if something is missing

@tdrz
Copy link
Collaborator

tdrz commented Jan 13, 2026

@tdrz merged upstream. I've updated this PR and the other for Build with the Parameter 32bit. Happy to hear if something is missing

@jpabbuehl
Nice! Did you link the submodule to the upstream?

@jpabbuehl
Copy link
Author

@tdrz I updated the submodule link, including electric-sql/postgres-pglite#58 Hope all is good

@tdrz
Copy link
Collaborator

tdrz commented Jan 21, 2026

@tdrz I updated the submodule link, including electric-sql/postgres-pglite#58 Hope all is good

@jpabbuehl Thank you! There seems to be a conflict with postgres-pglite, could you please have a look?

@jpabbuehl
Copy link
Author

My 32-bit fix was merged to upstream master (#2286, included in #2311).

However, upstream master has since moved to PG18 (#2315), so the build now fails with PG18 API incompatibilities:

error: use of undeclared identifier 'VAR_RETURNING_DEFAULT'
error: unknown type name 'pg_noreturn'
error: too many arguments to function call 'ExecInitRangeTable'

Since PGlite is still on PG17.5, I'd need the fix backported to AGE's PG17 branch.

@tdrz What do you think? Should I open a backport PR on apache/age for PG17, or is PGlite planning to upgrade to PG18 soon?

@tdrz
Copy link
Collaborator

tdrz commented Jan 25, 2026

My 32-bit fix was merged to upstream master (#2286, included in #2311).

💯

However, upstream master has since moved to PG18 (#2315), so the build now fails with PG18 API incompatibilities:

error: use of undeclared identifier 'VAR_RETURNING_DEFAULT'
error: unknown type name 'pg_noreturn'
error: too many arguments to function call 'ExecInitRangeTable'

@jpabbuehl That's very unfortunate, I was looking forward to deploying this soon. :(

Since PGlite is still on PG17.5, I'd need the fix backported to AGE's PG17 branch.

@tdrz What do you think? Should I open a backport PR on apache/age for PG17, or is PGlite planning to upgrade to PG18 soon?

As we don't have a clear date when we'll upgrade PGlite to PG18, I think it would be best to try to backport it to PG17 on AGE's repo. Thank you for your efforts, I know it must be a blow...

@jpabbuehl
Copy link
Author

opened a PR apache/age#2321

@jpabbuehl
Copy link
Author

will come soon apache/age#2321 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants