Skip to content

[Feature Request] Expose database locale/collation (bootstrap.initdb) in the database spec #446

Description

@adestis-mb

Problem. POST /v1/databases provides no way to set the database locale/collation. DatabaseSpec has no locale field, scripts.post_init runs after CREATE DATABASE (too late for the immutable datcollate/datctype), and postgresql_conf can't help since PG18 doesn't expose lc_collate/lc_ctype as runtime GUCs. The instances are Patroni-managed, and the control plane renders bootstrap.initdb: [data-checksums] with no override hook. Net effect: every database is forced to the container initdb default (UTF8 / libc / C / C.UTF-8). Locale-correct sorting (e.g. German) is only reachable per-column via explicit COLLATE, which every application query/schema must opt into.

Why it can't be worked around. Locale is immutable after CREATE DATABASE. The only lever is bootstrap.initdb at first bootstrap, which only the control plane controls. Forcing a re-bootstrap after the fact requires clearing Patroni's DCS state (instance etcd credentials are correctly scoped to forbid this) and destroys the provisioned database — and the control plane still reports the instance available afterward, so the divergence is silent.

Request. Add optional locale fields to the database spec, passed through to Patroni bootstrap.initdb, applied identically on every node of the database, e.g.:

"locale": {
   "provider": "icu",            // icu | libc | builtin
   "icu_locale": "de-DE",
   "encoding": "UTF8",
   "lc_collate": "C",
   "lc_ctype": "C.UTF-8"
}

Since all nodes of a Spock multi-master database must be byte-identical in collation, this belongs at the spec level (one value enforced cluster-wide), not per-instance. ICU is preferable to libc because the required de_* libc locales aren't present in the image, and ICU carries collversion for drift detection.

▎ Verified on: control-plane v0.9.0, pgedge-postgres:18.4-spock5.0.9-standard-1. Direct CREATE DATABASE … LOCALE_PROVIDER icu ICU_LOCALE 'de-DE' in that image works and sorts German correctly — the gap is purely the control-plane pass-through.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions