How to Configure Node Storage Backends in PrivateGPT: Simple File vs PostgreSQL

Set nodestore.database to "simple" for file-based storage or "postgres" for PostgreSQL, then install the appropriate extras package if using the database backend.

PrivateGPT separates vector embeddings from metadata storage, allowing you to configure node storage backends independently from your vector database. This flexibility lets you choose between zero-configuration file storage for local development or PostgreSQL for production deployments requiring concurrent access and durability.

Understanding Node Storage Architecture

PrivateGPT stores index metadata and document metadata (collectively called the "node store") separately from the vector embeddings. The NodeStoreComponent in private_gpt/components/node_store/node_store_component.py initializes the appropriate backend during application startup based on your configuration.

Simple File Storage Backend

The simple backend uses SimpleIndexStore and SimpleDocumentStore from llama-index to persist metadata as JSON files on disk. This is the default configuration requiring no external dependencies.

  • Persistence location: Files under the local_data_path directory (default: local_data/private_gpt)
  • Required packages: None (included with base installation)
  • Best for: Single-instance deployments, development, and testing

PostgreSQL Storage Backend

The postgres backend uses PostgresIndexStore and PostgresDocumentStore from llama-index to store metadata in PostgreSQL tables, enabling multiple PrivateGPT instances to share the same metadata.

  • Persistence location: Tables in a PostgreSQL database
  • Required packages: storage-nodestore-postgres extra
  • Best for: Production deployments, high availability, and multi-instance setups

Configuring the Node Storage Backend

The backend selection is controlled by the nodestore.database field in your YAML configuration files.

Settings Model and Allowed Values

In private_gpt/settings/settings.py, the NodeStoreSettings model restricts the database value to specific literals:

class NodeStoreSettings(BaseModel):
    database: Literal["simple", "postgres"]

This validation ensures only supported backends can be configured.

YAML Configuration Examples

Simple file storage (default in settings.yaml):

nodestore:
  database: simple

PostgreSQL storage (example from settings-ollama-pg.yaml):

nodestore:
  database: postgres

postgres:
  host: localhost
  port: 5432
  user: postgres
  password: postgres
  database: private_gpt
  schema_name: public

PrivateGPT loads these settings at startup and instantiates the corresponding storage classes.

Installing PostgreSQL Dependencies

When selecting the PostgreSQL backend, you must install the optional dependencies. If the required packages are missing, NodeStoreComponent raises an ImportError with explicit installation instructions.

Install the extra using Poetry:

poetry install --extras storage-nodestore-postgres

Or if using pip with the private package index:

pip install private-gpt[storage-nodestore-postgres]

The component imports PostgresIndexStore and PostgresDocumentStore from llama_index.storage.index_store.postgres and llama_index.storage.docstore.postgres respectively only after this installation.

How the Backend Selection Works

The NodeStoreComponent class in private_gpt/components/node_store/node_store_component.py implements the backend switching logic using Python's match statement:

match settings.nodestore.database:
    case "simple":
        self.index_store = SimpleIndexStore.from_persist_dir(
            persist_dir=str(local_data_path)
        )
        self.doc_store = SimpleDocumentStore.from_persist_dir(
            persist_dir=str(local_data_path)
        )
    case "postgres":
        from llama_index.storage.docstore.postgres import PostgresDocumentStore
        from llama_index.storage.index_store.postgres import PostgresIndexStore
        
        self.index_store = PostgresIndexStore.from_params(
            **settings.postgres.model_dump(exclude_none=True)
        )
        self.doc_store = PostgresDocumentStore.from_params(
            **settings.postgres.model_dump(exclude_none=True)
        )

This construction happens once at application startup when the dependency injection container creates the singleton instance of NodeStoreComponent.

Accessing the Node Store in Code

The NodeStoreComponent is registered as a singleton in the dependency injection container. You can access the initialized stores throughout your application:

from private_gpt.di import global_injector
from private_gpt.components.node_store.node_store_component import NodeStoreComponent

# Retrieve the singleton component

node_store = global_injector.get(NodeStoreComponent)

# Access the underlying stores

index_store = node_store.index_store
doc_store = node_store.doc_store

The concrete implementations (SimpleIndexStore or PostgresIndexStore) are determined entirely by your YAML configuration, allowing you to switch backends without modifying application code.

Summary

  • Node storage in PrivateGPT handles index and document metadata separately from vector embeddings, configured via nodestore.database in your YAML settings.
  • Simple file storage requires no extra dependencies and persists JSON files to local_data/private_gpt, ideal for development.
  • PostgreSQL storage requires installing the storage-nodestore-postgres extra and provides durable, shared metadata storage for production.
  • The NodeStoreComponent in private_gpt/components/node_store/node_store_component.py automatically instantiates the correct backend based on your configuration settings.

Frequently Asked Questions

How do I migrate from simple file storage to PostgreSQL?

PrivateGPT does not provide an automatic migration tool between node store backends. To migrate, you must export your index and document metadata from the simple file stores (JSON files in local_data/private_gpt) and import them into PostgreSQL using llama-index's storage APIs, or rebuild your index from source documents after switching the configuration.

Can I use different backends for the node store and vector store?

Yes. PrivateGPT decouples these concerns entirely. You can configure the node store to use PostgreSQL while using a local vector store like Chroma or Qdrant, or vice versa. Each component reads its own configuration section independently.

What happens if I select postgres but forget to install the extras?

The application will fail to start with an ImportError raised by NodeStoreComponent. The error message explicitly instructs you to run poetry install --extras storage-nodestore-postgres to resolve the missing dependencies.

Is PostgreSQL node storage more performant than simple file storage?

PostgreSQL provides better concurrency and durability for multi-instance deployments, but simple file storage has lower latency for single-instance, local development. For high-throughput production environments with multiple PrivateGPT instances, PostgreSQL is the recommended backend.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →