Gucs config
Skill matejformanek/postgres-claude/.claude/skills/gucs-config
Turn Claude Code into a long-term collaborator on PostgreSQL internals — cited knowledge corpus, agent skills, slash commands, and task-shaped scenarios for backend hacking.
npx -y skills add matejformanek/postgres-claude --skill gucs-configAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Add or modify a custom GUC variable in a PostgreSQL backend patch or extension — covers DefineCustomBoolVariable / IntVariable / RealVariable / StringVariable / EnumVariable, picking the right GucContext (PGC_POSTMASTER / PGC_SIGHUP / PGC_SUSET / PGC_USERSET), MarkGUCPrefixReserved, the check/assign/show hook trio, GUC_LIST_INPUT / GUC_LIST_QUOTE / GUC_UNIT_MS / GUC_UNIT_KB / GUC_REPORT / GUC_EXPLAIN flags, and string-GUC guc_malloc rules. Use whenever a PG patch or extension calls DefineCustom*Variable, picks a GucContext, wires check/assign/show hooks, debugs a placeholder GUC, or marks a GUC reserved via MarkGUCPrefixReserved. Skip for DBA tuning of shared_buffers / max_connections / work_mem in production, dotenv / Viper / Dynaconf / Spring @Value configuration libraries, Kubernetes ConfigMap, Terraform variables, and non-PG application config systems.
SKILL.md
11.2 KB, ~2.7k tokens by cl100k_base, as published. Nobody here has run it
gucs-config — custom GUC variables
This is the procedural cookbook for adding custom GUC variables to a
PostgreSQL backend patch or extension. For the conceptual model see
knowledge/idioms/guc-variables.md.
This skill is one of three siblings that share the
_PG_init / postmaster-lifecycle boundary:
- gucs-config (this skill) — custom GUC variables.
bgworker-and-extensions— RegisterBackgroundWorker, shared-library hooks.parallel-query— ParallelContext + parallel-safe markings.
1. Picking the right Define*Variable
Five typed entry points, all in utils/guc.h.
[verified-by-code source/src/include/utils/guc.h:358-416]
| Type | Function | Notes |
|---|---|---|
| bool | DefineCustomBoolVariable | |
| int | DefineCustomIntVariable | with minValue / maxValue |
| double | DefineCustomRealVariable | with minValue / maxValue |
| string | DefineCustomStringVariable | valueAddr is char **, see §5 |
| enum | DefineCustomEnumVariable | takes a const struct config_enum_entry[] |
All five take the same trailing trio of hooks: check_hook, assign_hook,
show_hook (any can be NULL).
2. GucContext — when the value can change
[verified-by-code source/src/include/utils/guc.h:71-80]
GucContext | When the user can change it |
|---|---|
PGC_INTERNAL | Never — display-only (e.g. server_version). |
PGC_POSTMASTER | Only at postmaster startup (postgresql.conf / cmd line). |
PGC_SIGHUP | Postmaster start OR config-reload (SIGHUP / pg_reload_conf()). |
PGC_SU_BACKEND | Start of backend, superusers can pass via startup packet. |
PGC_BACKEND | Start of backend (libpq PGOPTIONS), then fixed. |
PGC_SUSET | Any time by a superuser, including SET. |
PGC_USERSET | Any time by anyone. |
Rule of thumb: pick the loosest context that's still safe. If
changing the value mid-session would require restarting a worker or
reallocating shared memory, use PGC_POSTMASTER. If it just changes
a runtime threshold, use PGC_SIGHUP or PGC_SUSET.
3. Skeleton — _PG_init for an extension with GUCs
void
_PG_init(void)
{
DefineCustomIntVariable("my_ext.naptime",
"Seconds between scans.",
NULL, /* long_desc */
&my_naptime, /* int *valueAddr */
10, /* boot_val */
1, INT_MAX, /* min, max */
PGC_SIGHUP,
GUC_UNIT_S, /* flags — UNIT_S = seconds */
NULL, NULL, NULL); /* check/assign/show */
DefineCustomStringVariable("my_ext.database",
"DB to connect to.",
NULL,
&my_database,
"postgres",
PGC_POSTMASTER,
0,
NULL, NULL, NULL);
/* MUST be called AFTER all DefineCustom* calls. */
MarkGUCPrefixReserved("my_ext");
}
[verified-by-code source/src/test/modules/worker_spi/worker_spi.c:303-360]
4. MarkGUCPrefixReserved
Call exactly once per extension, after every DefineCustom*Variable for
your prefix. It does two things:
- Removes any placeholder GUCs (
GUC_CUSTOM_PLACEHOLDER) under that prefix — these get created when a config file mentions a custom variable before the defining extension loads. Without removal, parallel-worker startup later trips over them. - Adds the prefix to a list so future placeholders under it are refused —
typos in
postgresql.conf(my_ext.napitme) now produce a clear error instead of silently being accepted.
[verified-by-code source/src/backend/utils/misc/guc.c:5185-5228]
The old name EmitWarningsOnPlaceholders is still a #define alias —
prefer the new name in new code. [verified-by-code
source/src/include/utils/guc.h:421]
5. String GUCs and guc_malloc
For string GUCs, valueAddr is a char **. The pointed-to storage is
owned by guc.c and must be allocated with guc_malloc / guc_strdup —
never palloc. If a check_hook wants to replace the proposed value
it must guc_malloc the new value and guc_free the old one. Use
guc_realloc to grow an existing guc_malloc allocation (typical for a
derived extra payload). All four functions live in
source/src/include/utils/guc.h:473-476.
[from-README source/src/backend/utils/misc/README:50-62]
6. The hook trio
check_hook(newval *, void **extra, GucSource source) → bool
Signature varies by GUC type — the first argument's exact pointer type matches the variable's storage:
| GUC type | check_hook first arg |
|---|---|
| bool | bool *newval |
| int | int *newval |
| real | double *newval |
| string | char **newval (so *newval is the proposed char *) |
| enum | int *newval (enum encoded as int) |
[from-README source/src/backend/utils/misc/README:25-30]
- Validate the proposed value; return false on reject.
- May modify
*newvalto canonicalize (round, lowercase, ...). - May allocate an
extrastruct withguc_mallocand return it through*extrato pass derived data to the assign hook. - For error detail:
GUC_check_errdetail(...),GUC_check_errhint(...),GUC_check_errcode(...),GUC_check_errmsg(...)— neverereport(ERROR)directly except on OOM.GUC_check_errcode(sqlerrcode)overrides the default rejection SQLSTATE (ERRCODE_INVALID_PARAMETER_VALUE, 22023); only override when you have a more specific code. - May run outside any transaction (bootstrap, postmaster startup,
config reload). Guard catalog lookups with
IsTransactionState(). - May also be called just to validate without assigning — must not have side effects.
- For
GUC_LIST_INPUTGUCs (see §7), parse*newvalinside the check_hook withSplitIdentifierString(rawstring, ',', &elemlist)(identifier-style lists) orSplitGUCList(rawstring, ',', &elemlist)(general case). Both live insource/src/include/utils/varlena.h:33-37; theypstrdupelements andpfree/list_freeis the caller's job. Don't roll your own splitter — these match how the parser handlessearch_path, including quoted elements.
[from-README source/src/backend/utils/misc/README:25-75]
assign_hook(newval, void *extra) → void
- Cannot fail (no return). Do all fallible work in the check hook.
- May be called during transaction rollback → no catalog lookups.
[from-README source/src/backend/utils/misc/README:78-109]
show_hook(void) → const char *
- Customise what SHOW displays. Static buffer is fine; not reentrant.
[from-README source/src/backend/utils/misc/README:112-117]
7. Useful flags bits
[verified-by-code source/src/include/utils/guc.h:214-242]
| Flag | Effect |
|---|---|
GUC_LIST_INPUT | Value is a comma-separated list — needed to use lists at all. |
GUC_LIST_QUOTE | Each list element is double-quoted on serialization. Required for lists of identifiers (e.g. search_path). |
GUC_UNIT_KB / _MB / _BYTE / _BLOCKS | Int GUC understands '128MB'. |
GUC_UNIT_MS / _S / _MIN | Time units. |
GUC_NOT_IN_SAMPLE | Don't include in generated postgresql.conf.sample. |
GUC_SUPERUSER_ONLY | Hide value from non-superusers in pg_settings. |
GUC_DISALLOW_IN_FILE | Cannot appear in config file (set only at runtime). |
GUC_DISALLOW_IN_AUTO_FILE | Cannot be set by ALTER SYSTEM. |
GUC_REPORT | Auto-send ParameterStatus to client on change. |
GUC_EXPLAIN | Include in EXPLAIN (SETTINGS) output. |
GUC_ALLOW_IN_PARALLEL | OK to set inside a parallel-mode block. |
8. GUC state under workers (cross-cutting)
-
Parallel workers — GUC state is serialized by the leader and restored in each worker by
ParallelWorkerMainbefore your code runs. Workers see exactly the leader's GUC values at launch time. If aPGC_USERSETGUC changes mid-flight, in-flight workers do not see the change. Seeparallel-queryfor the launch mechanics. -
Background workers (non-parallel) — GUC state is whatever
postgresql.confsays at start. To honour SIGHUP, installSignalHandlerForConfigReloadand callProcessConfigFile(PGC_SIGHUP)whenConfigReloadPendingis set. Seebgworker-and-extensionsfor the signal-handling skeleton.
9. Checklist
-
_PG_initdefines every custom GUC. -
MarkGUCPrefixReserved(prefix)is called after all definitions. - String storage uses
guc_malloc/guc_strdup, neverpalloc. -
check_hookis side-effect-free and usesGUC_check_errdetail(notereport(ERROR)) for validation failures. -
check_hookguards catalog lookups withIsTransactionState(). - Right
GucContextchosen (don't usePGC_USERSETif the change would require restarting workers). - Unit flag set on int GUCs that represent size or time.
- List GUCs have
GUC_LIST_INPUT, andGUC_LIST_QUOTEif elements are identifiers.
10. Useful greps
- All custom GUC definitions:
grep -RIn 'DefineCustom\(Bool\|Int\|Real\|String\|Enum\)Variable' source/src - All check / assign hooks in tree:
grep -RIn 'check_hook\|assign_hook' source/src/include/utils/guc.h
Cross-references
.claude/skills/bgworker-and-extensions/SKILL.md—_PG_initflow for the surrounding extension; SIGHUP signal handler for picking up config reloads..claude/skills/parallel-query/SKILL.md— how GUCs get restored in parallel workers;GUC_ALLOW_IN_PARALLELflag..claude/skills/extension-development/SKILL.md—_PG_init,.controlfile,shared_preload_libraries..claude/skills/coding-style/SKILL.md— backend C style for the hook functions..claude/skills/error-handling/SKILL.md—GUC_check_errdetailvsereport(ERROR); OOM contract.knowledge/idioms/guc-variables.md— conceptual model.knowledge/files/src/include/utils/guc.h.md— per-file doc for the public API surface.knowledge/files/src/backend/utils/misc/guc.c.md— per-file doc for the implementation.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.