Skip to content

feat: add S3Checkpoint for serverless/containerized environments#402

Open
evanerwee wants to merge 1 commit into
awslabs:mainfrom
evanerwee:feat/s3-checkpoint
Open

feat: add S3Checkpoint for serverless/containerized environments#402
evanerwee wants to merge 1 commit into
awslabs:mainfrom
evanerwee:feat/s3-checkpoint

Conversation

@evanerwee

Copy link
Copy Markdown
Contributor

Description

Add S3-backed checkpoint (S3Checkpoint) that stores markers as zero-byte S3 objects instead of local files. Enables checkpointing in ECS Fargate, Lambda, and EKS environments where local disk is ephemeral.

Changes

  • New S3Checkpoint class — drop-in replacement for Checkpoint with same interface
  • S3CheckpointFilter — uses HEAD request instead of os.path.exists()
  • S3CheckpointWriter — uses PUT zero-byte object instead of open(path, "a")
  • Export added to __init__.py
  • 15 unit tests

Problem

Related issue: #401

The existing Checkpoint class uses local filesystem markers (os.path.exists, os.makedirs, open). This fails in serverless/containerized environments (Fargate, Lambda, EKS) where local disk is ephemeral and does not survive container restarts or SQS message retries.

Testing

  • Unit tests added/updated
  • Integration tests added (as appropriate)
  • Existing tests pass (pytest)
  • Tested manually (describe below)

Manual testing: verified syntax passes ast.parse(), imports resolve correctly against the existing module structure.

Checklist

  • Code follows existing style and conventions
  • License headers present on new files
  • Documentation updated (if applicable)
  • No breaking changes (or clearly documented)

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

Add S3-backed checkpoint that stores markers as zero-byte S3 objects
instead of local files. Enables checkpointing in ECS Fargate, Lambda,
and EKS environments where local disk is ephemeral.

- S3CheckpointFilter: HEAD request to check if node was processed
- S3CheckpointWriter: PUT zero-byte object as completion marker
- S3Checkpoint: drop-in replacement for Checkpoint with same interface
  (add_filter, add_writer, enabled)

The local Checkpoint class uses os.path.exists/os.makedirs/open which
requires persistent local filesystem. S3Checkpoint uses the same
pattern but backed by S3, surviving container restarts and retries.

Usage:
    from graphrag_toolkit.lexical_graph.indexing.build import S3Checkpoint

    checkpoint = S3Checkpoint(
        checkpoint_name='enrichment-run-001',
        bucket_name='my-pipeline-bucket',
        key_prefix='checkpoints/tenant-a'
    )
    graph_index.extract(docs, handler=extracted_docs, checkpoint=checkpoint)

@mykola-pereyma mykola-pereyma left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you for putting this together — the problem is real and we understand the need for checkpointing in Fargate/Lambda environments.

We have #325 on our implementation roadmap which covers this use case as part of a broader checkpoint/state-store redesign. That design introduces a URI-based factory pattern (matching how GraphStoreFactory and VectorStoreFactory already work) with support for multiple backends (S3, DynamoDB) and document-level progress tracking for distributed workers.

A few things we noticed in this PR that the broader design would address differently:

  • The parameter is accepted but never used (the S3 client comes from GraphRAGConfig)
  • No shared interface between Checkpoint and S3Checkpoint — if we add DynamoDB later it would be a third copy
  • Per-node HEAD requests in the filter path would be a bottleneck at scale (list_objects_v2 with prefix can batch-check)

We appreciate the contribution and the detailed issue write-up. Would you be open to collaborating on #325 instead? Your experience running this on Fargate would be valuable input for the design — especially around the failure modes and retry patterns you encountered.

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