Skip to content

Project Format

A pglifecycle project is a directory of YAML files, one file per database object, validated against the JSON-Schema definitions in schemata/.

my-project/
├── project.yaml          # name, encoding, extensions, languages
├── schemata/             # one file per schema
│   └── test.yaml
├── tables/               # <schema>/<table>.yaml
│   └── test/
│       └── users.yaml
├── views/                # <schema>/<view>.yaml
├── materialized_views/
├── functions/            # <schema>/<function>.yaml
├── sequences/
├── domains/
├── types/                # one container file per schema
├── roles/                # <role>.yaml
├── users/
├── groups/
└── ...                   # aggregates, casts, collations, conversions,
                          # event_triggers, operators, publications,
                          # servers, subscriptions, tablespaces,
                          # text_search, user_mappings, dml

Objects are structured data, not SQL. A table file, for example:

---
name: users
schema: test
owner: postgres
columns:
  - name: id
    data_type: uuid
    nullable: false
    default: uuid_generate_v4()
  - name: email
    data_type: test.email_address
    nullable: false
indexes:
  - name: users_unique_email
    unique: true
    method: btree
    columns:
      - name: email
primary_key:
  - id

Conventions

  • The file location implies schema and name; both may be omitted from the file body and are injected on load.
  • A dependencies key (e.g. dependencies: {tables: [test.users]}) records relationships the topological sort cannot infer, such as foreign-key ordering between tables.
  • ACL grants and revocations live on the grantee's role, user, or group file under grants:/revocations:, keyed by object:
---
name: PUBLIC
create: false
grants:
  schemata:
    test:
      - USAGE
  • create: false defines a role without creating it — used for built-in pseudo-roles like PUBLIC.