Skip to content

feat(checkpoint-postgres): Add PostgresStore for LangGraph.js #1242

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 34 commits into
base: 0.4
Choose a base branch
from

Conversation

abogacki
Copy link
Contributor

Implement PostgreSQL Store with Vector Search Capabilities

Overview

This PR implements a PostgreSQL-based store for LangGraph.js inspired by #887 and Python implementation. The implementation includes comprehensive vector similarity search, hybrid search (combining vector and text search), and TTL management for automatic data expiration.

Key Features

  • Modular architecture with specialized components for different responsibilities
  • Vector similarity search with support for multiple distance metrics (cosine, L2, inner product)
  • Hybrid search combining vector similarity and full-text search
  • Advanced filtering with rich query operators ($eq, $gt, $lt, $in, etc.)
  • Automatic TTL management with configurable expiration settings
  • Support for PostgreSQL's pgvector extension for efficient vector operations

Implementation Details

  • Split the monolithic implementation into specialized modules:
    • database-core.js: Core connection and transaction management
    • database-setup.js: Schema initialization and migration
    • crud-operations.js: Basic CRUD operations
    • search-operations.js: Advanced search capabilities
    • vector-operations.js: Vector embedding and similarity calculations
    • ttl-manager.js: Expiration and cleanup management
    • query-builder.js: SQL query construction
  • Added comprehensive TypeScript types for better developer experience
  • Implemented efficient text extraction from JSON documents using configurable field paths
  • Added extensive test coverage for all features

@@ -0,0 +1,87 @@
/* eslint-disable no-process-env */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've decided to group and split integration tests by tested module/functionality, as originally the file had over 1,5 k lines of code and would be harder to maintain

@abogacki abogacki changed the title Langgraph postgres store feat(store-postgres): Add PostgresStore for LangGraph.js May 30, 2025
@abogacki abogacki marked this pull request as ready for review May 30, 2025 13:38
@abogacki abogacki marked this pull request as draft May 30, 2025 18:48
@abogacki abogacki marked this pull request as ready for review June 2, 2025 06:41
@abogacki abogacki marked this pull request as draft June 6, 2025 07:19
@abogacki abogacki marked this pull request as ready for review June 6, 2025 09:52
Copy link

changeset-bot bot commented Jul 11, 2025

🦋 Changeset detected

Latest commit: b62ee3f

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@langchain/langgraph-checkpoint-postgres Minor

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@abogacki
Copy link
Contributor Author

Is there a chance this will be reviewed? Is there anyone I could mention? Perhaps @dqbd

@dqbd
Copy link
Collaborator

dqbd commented Jul 17, 2025

Hello! Thank you for the PR, will be reviewing thoroughly shortly. At first glance I think we want to have this implementation in the same package as the checkpointer

@dqbd dqbd changed the base branch from main to 0.4 July 22, 2025 14:43
@dqbd dqbd force-pushed the langgraph-postgres-store branch from 2abafe9 to 116fc46 Compare July 22, 2025 14:52
@dqbd dqbd changed the title feat(store-postgres): Add PostgresStore for LangGraph.js feat(checkpoint-postgres): Add PostgresStore for LangGraph.js Jul 22, 2025
@abogacki
Copy link
Contributor Author

abogacki commented Jul 22, 2025

Awesome, thank you for applying changes, lmk if there's anything I should work on/adjust :)

constructor(private core: DatabaseCore) {}

async initialize(): Promise<void> {
await this.core.withClient(async (client) => {
Copy link
Collaborator

@dqbd dqbd Jul 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth adding a migration mechanism similar to the postgres checkpointer?

updated_at,
CASE
WHEN $2::text IS NOT NULL THEN
ts_rank(to_tsvector('english', value::text), plainto_tsquery('english', $2::text))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Worth making this configurable?

/**
* Close all database connections.
*/
async end(): Promise<void> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we consolidate end() with stop()?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, we need to make start() and stop() potentially async as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, technically the BasteStore interface requires these methods to be synchronous. I'll apply the changes, but from what I can see, to maintain cohesion, I will:

  • make start/stop asynchronous in BaseStore
  • I'll make PregelLoop.initialize() and PregelLoop.tick() methods await the store.start()
  • make all other concrete implementations use async start/stop

@abogacki abogacki requested a review from dqbd July 23, 2025 06:16
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.

3 participants