PgSTAC

repository·main·Indexed 42 days ago

https://github.com/stac-utils/pgstac

A high-performance PostgreSQL schema and set of functions for managing Spatio-Temporal Asset Catalogs (STAC). It provides the database layer for STAC APIs, supporting STAC Filters and CQL2 search. The ecosystem includes the core SQL schema, pgstac-migrate for database upgrades (v0.9.11-dev), a Rust-based CLI for data loading and querying, and pypgstac-rs for Python read/write operations.

Tokens
30.2K
Snippets
98
Records
128
Agent score
53%

What's inside PgSTAC

  1. Overview of the pgstac Rust client and CLI

    main

    The src/pgstac-rs crate provides a high-performance Rust implementation for interacting with a PgSTAC database. It includes:

    • A Read Engine: Handles search_plan and collection_search_plan, performing band stepping, hydration (converting EWKB to GeoJSON and merging fragments), keyset token minting, and STAC fields projection in Rust. This moves CPU-intensive tasks off the database.
    • A Connection Pool: The PgstacPool (available via the pool feature) provides an async read API.
    • Dump/Export Capabilities: A library and CLI tool (pgstac) for exporting data (available via export or cli features).
    • Python Bindings: A Python wheel (pgstac) built with maturin (available via the python feature).
  2. Overview of PgSTAC

    main

    PgSTAC is a set of PostgreSQL SQL functions and schemas designed to build highly performant databases for Spatio-Temporal Asset Catalogs (STAC). It provides core data models and functions to enable a STAC API directly from a PostgreSQL database, supporting STAC Filters and CQL2 search.

    Note that PgSTAC operates entirely within the database and does not provide an HTTP-facing API itself. To expose a STAC API, you can use backends like STAC FastAPI or Franklin.

  3. How promoted fields work in pgstac

    main

    Promoted fields are a performance optimization used by pgstac. Instead of storing all STAC properties in a single properties JSONB column, a curated set of high-cardinality, well-known fields are extracted into dedicated, typed native SQL columns.

    Key behaviors:

    • Ingest: The content_dehydrate() function reads properties from item.properties, casts them to the target SQL type, and writes them to the matching column.
    • Read: The promoted_properties_from_item() function rehydrates these column values back into the STAC JSON object when reading.
    • Querying: Promoted fields are automatically registered as queryables. CQL2 filters on these fields resolve to direct column comparisons (allowing for index-only scans) rather than expensive JSONB path extractions.
    • Non-promoted fields: Any property not in the promoted list (including vendor-specific fields or new extensions) is still stored in the properties JSONB column and remains fully queryable via CQL2 using standard JSONB extraction.
    Note: This is a conceptual explanation of the internal mechanism. No direct API call is provided for this internal process.
  4. Configure PgSTAC partitioning

    main

    By default, PgSTAC partitions data by collection. Collections can be further partitioned by year or month.

    Crucial: Partitioning must be configured before loading any data. You configure it by setting the partition_trunc flag on a collection. Aim to keep each partition under a few hundred thousand rows to maintain performance.

    -- Set a collection to be partitioned by month
    UPDATE collections SET partition_trunc='month' WHERE id='<collection id>';
  5. Configure and run automated collection extent updates

    main

    To automatically adjust collection spatial and temporal extents as items are ingested, set the configuration pgstac.update_collection_extent to true.

    To minimize transaction overhead during ingestion, combine this with pgstac.use_queue, which defers the extent updates to a queue. This queue must be drained manually or via a scheduler.

    How to drain the queue:

    • CLI: Run pgstac runqueue (which executes CALL run_queued_queries()).
    • SQL: Execute CALL run_queued_queries(); directly.
    • Automation: Use pg_cron to schedule the queue processing.
    # Manually run the queue
    pgstac runqueue
  6. Components of the PgSTAC ecosystem

    main

    The PgSTAC project consists of several specialized packages:

    • pgstac (SQL): The core SQL schema and functions for STAC data models.
    • pgstac-migrate: A focused migration package for managing database upgrades.
    • pgstac (Rust CLI): A Rust-based CLI tool used for loading data, searching, querying, managing extensions, and maintenance.
    • pypgstac-rs: A Rust-backed Python extension designed for read/write operations, specifically for use with stac-fastapi-pgstac.
  7. Install and configure PgSTAC requirements

    main

    PgSTAC requires PostgreSQL >= 13, PostGIS >= 3, and the btree_gist extension. For optimal performance, use PostGIS >= 3.1. All PgSTAC objects are installed into the pgstac schema, which must be included in your PostgreSQL search_path to function correctly.

    -- Set search_path for a specific user
    ALTER ROLE <user> SET SEARCH_PATH TO pgstac, public;
    
    -- Or set it for the entire database
    ALTER DATABASE <database> SET search_path TO pgstac, public;
  8. Requirements for adding or removing promoted fields

    main

    For pgstac developers, adding or removing a promoted field is a high-impact change that requires synchronizing updates across six specific locations in the SQL schema files (src/pgstac/sql/003a_items.sql and src/pgstac/sql/002a_queryables.sql).

    Failure to update all six locations will break the promotion lifecycle. The required locations are:

    1. items TABLE DDL: The actual column declaration.
    2. content_dehydrate(): The logic to extract the value from JSONB during ingest.
    3. promoted_item_property_defs(): The metadata registry mapping the STAC property name to the SQL column.
    4. promoted_properties_from_item(): The logic to rehydrate the column value back into the JSONB object during read.
    5. promoted_items_column_list(): The ordered array used for auto-derived logic.
    6. items_staging_dehydrate(): The enriched SELECT statement used for all staging branches.
  9. Run tests for pgstac-rs

    main

    Testing requires a running pgstac database.

    1. From the root of the pgstac repository, start the server:
      scripts/server
    2. In another terminal, run the tests:
      cargo test --manifest-path src/pgstac-rs/Cargo.toml

    Each test runs in its own transaction and is rolled back automatically.

    Customizing the test database connection: By default, tests connect to postgresql://username:password@localhost:5439/postgis. To use a different database, set the PGSTAC_RS_TEST_DB environment variable:

    PGSTAC_RS_TEST_DB=postgresql://otherusername:otherpassword@otherhost:7822/otherdbname cargo test --manifest-path src/pgstac-rs/Cargo.toml
    # Start server from repo root
    scripts/server
    
    # Run tests
    cargo test --manifest-path src/pgstac-rs/Cargo.toml
  10. Manage PgSTAC database roles and permissions

    main

    PgSTAC uses three primary roles to manage access and security:

    • pgstac_admin: The owner of all objects within the pgstac schema. Use this role for running migrations.
    • pgstac_ingest: Has read/write privileges on all tables. Use this for data ingestion or when using the transactions extension with stac-fastapi-pgstac.
    • pgstac_read: Has read-only access to items and collections, but can still write to logging tables.

    You can use these roles directly by assigning a password, or grant them to an existing user.

    -- To use a role directly with a password
    ALTER ROLE pgstac_read LOGIN PASSWORD '<password>';
    
    -- To grant permissions to an existing user
    GRANT pgstac_read TO <user>;
  11. Backup and restore PgSTAC databases

    main

    PgSTAC databases should be backed up using standard pg_dump with the custom format (-Fc).

    Important: Do not use pg_restore directly. Because PgSTAC functions call PostGIS functions without schema qualification, a standard pg_restore will fail. Instead, use the provided pgstac_restore script, which manages the search_path during the restore process.

    Backup Command

    pg_dump -Fc --schema=pgstac -f pgstac_backup.dump mydatabase

    Restore Command

    # Restore into a fresh database, creating extensions and skipping role requirements
    pgstac_restore -d target_db --create-extensions --no-roles pgstac_backup.dump

    Restore Options:

    • --create-extensions: Creates PostGIS, btree_gist, and unaccent if missing.
    • --no-roles: Skips ownership/privilege restoration (useful if target doesn't have pgstac roles).
    • -d, --dbname: Target database name.
    # Recommended backup command
    pg_dump -Fc --schema=pgstac -f pgstac_backup.dump mydatabase
    
    # Recommended restore command
    pgstac_restore -d target_db --create-extensions --no-roles pgstac_backup.dump
  12. Perform maintenance and system checks

    main

    To keep statistics and constraints valid, run these maintenance procedures periodically (e.g., via pg_cron):

    • validate_constraints(): Ensures data constraints are up-to-date.
    • analyze_items(): Updates statistics for the items table.

    To check if your system settings are optimized for PgSTAC, use check_pgstac_settings, passing the total available memory of your database system.

    -- Schedule maintenance (requires pg_cron)
    SELECT cron.schedule('0 * * * *', 'CALL validate_constraints();');
    SELECT cron.schedule('10, * * * *', 'CALL analyze_items();');
    
    -- Check system settings recommendations
    SELECT * FROM check_pgstac_settings('32GB');
    
    -- Identify unused indexes to improve performance
    SELECT
        relname, indexrelname, idx_scan, last_idx_scan, idx_tup_read, idx_tup_fetch,
        pg_relation_size(relid) as index_bytes, 
        pg_size_pretty(pg_relation_size(relid)) as index_size
    FROM pg_stat_user_indexes
    WHERE schemaname = 'pgstac'
    ORDER BY idx_scan ASC;