{"skill":{"slug":"supabase-checkpointer","displayName":"Supabase LangGraph Checkpointer","summary":"Durable LangGraph checkpointing via Supabase REST API (PostgREST) — no direct Postgres connection needed. Use when deploying LangGraph graphs to ephemeral pl...","description":"---\nname: supabase-checkpointer\ndescription: Durable LangGraph checkpointing via Supabase REST API (PostgREST) — no direct Postgres connection needed. Use when deploying LangGraph graphs to ephemeral platforms (Railway, Fly, Cloud Run) where in-memory state is lost on redeploy, and you need interrupt/resume to survive process death. Works with any Supabase project using the existing service role key.\n---\n\n# Supabase REST Checkpointer for LangGraph\n\n## Problem\n\nLangGraph's `MemorySaver` stores state in-process. Ephemeral deployments (Railway, Fly, etc.) kill processes on redeploy, losing all interrupted graph state. `PostgresSaver` needs a direct Postgres connection string, which may not be available.\n\n## Solution\n\nA `BaseCheckpointSaver` implementation that stores checkpoints via Supabase's PostgREST API using the existing Supabase client. No direct Postgres connection needed.\n\n## Setup\n\n### 1. Create Tables\n\nRun `scripts/create_tables.sql` in Supabase (via SQL editor or `exec_sql` RPC):\n\n```sql\nCREATE TABLE langgraph_checkpoints (\n    thread_id TEXT NOT NULL,\n    checkpoint_ns TEXT NOT NULL DEFAULT '',\n    checkpoint_id TEXT NOT NULL,\n    parent_checkpoint_id TEXT,\n    type TEXT,\n    checkpoint JSONB NOT NULL,\n    metadata JSONB DEFAULT '{}',\n    created_at TIMESTAMPTZ DEFAULT now(),\n    PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id)\n);\n\nCREATE TABLE langgraph_writes (\n    thread_id TEXT NOT NULL,\n    checkpoint_ns TEXT NOT NULL DEFAULT '',\n    checkpoint_id TEXT NOT NULL,\n    task_id TEXT NOT NULL,\n    idx INTEGER NOT NULL,\n    channel TEXT NOT NULL,\n    type TEXT,\n    blob JSONB,\n    PRIMARY KEY (thread_id, checkpoint_ns, checkpoint_id, task_id, idx)\n);\n```\n\n### 2. Use the Checkpointer\n\n```python\nfrom supabase import create_client\nfrom supabase_checkpointer import SupabaseCheckpointer\n\nclient = create_client(url, key)\ncheckpointer = SupabaseCheckpointer(client)\ngraph = builder.compile(checkpointer=checkpointer)\n```\n\n### 3. Fallback Chain (recommended)\n\n```python\ndef _create_checkpointer():\n    # 1. Try Supabase (durable across redeploys)\n    try:\n        from supabase_checkpointer import SupabaseCheckpointer\n        client = get_supabase_client()\n        if client:\n            return SupabaseCheckpointer(client)\n    except Exception:\n        pass\n\n    # 2. Try SQLite (survives process restarts within same deploy)\n    try:\n        from langgraph.checkpoint.sqlite import SqliteSaver\n        import sqlite3\n        return SqliteSaver(sqlite3.connect(\"checkpoints.db\", check_same_thread=False))\n    except Exception:\n        pass\n\n    # 3. Fallback: in-memory (lost on restart)\n    from langgraph.checkpoint.memory import MemorySaver\n    return MemorySaver()\n```\n\n## Implementation\n\nThe full implementation is in `scripts/supabase_checkpointer.py`. It implements all required `BaseCheckpointSaver` methods:\n\n- `put()` — Upsert checkpoint to `langgraph_checkpoints`\n- `put_writes()` — Upsert pending writes to `langgraph_writes`\n- `get_tuple()` — Fetch latest checkpoint + pending writes for a thread\n- `list()` — Iterate checkpoints for a thread (time-travel)\n\nAll data serialized as JSONB. Uses `json.dumps(obj, default=str)` for non-serializable types.\n\n## Key Details\n\n- **Thread isolation:** Each graph run uses a unique `thread_id` in the config\n- **Checkpoint ordering:** Uses `created_at DESC` for latest checkpoint lookup\n- **Write deduplication:** Composite primary key prevents duplicate writes\n- **Error tolerance:** All operations wrapped in try/except — logs errors but doesn't crash the graph\n- **No async required:** Uses synchronous Supabase client (PostgREST over HTTP)\n","tags":{"latest":"1.0.0"},"stats":{"comments":0,"downloads":184,"installsAllTime":0,"installsCurrent":0,"stars":0,"versions":1},"createdAt":1771899341786,"updatedAt":1778491624313},"latestVersion":{"version":"1.0.0","createdAt":1771899341786,"changelog":"Initial release","license":null},"metadata":null,"owner":{"handle":"brandonwadepackard-cell","userId":"s17f5y8stpzc3ms14zwb8qv1t588567a","displayName":"brandonwadepackard-cell","image":"https://avatars.githubusercontent.com/u/227546078?v=4"},"moderation":null}