PostgreSQL provides a powerful configuration system through GUC (Grand Unified Configuration). While most developers use built-in parameters, PostgreSQL also allows you to define custom configuration variables and attach hooks to control their behavior.
In this blog, you will learn how to implement and understand three important GUC hooks:
- Check_hook
- Assign_hook
- show_hook
This guide is based on a working implementation, including real code and observed results.
What Are GUC Hooks?
When you define a custom configuration parameter in PostgreSQL, you can attach hooks that control how values are handled internally.
1. check_hook
This hook is used to validate a new value before PostgreSQL accepts it.
- If validation fails - the value is rejected
- If validation succeeds - PostgreSQL proceeds
2. assign_hook
This hook is called after the value is accepted and applied.
- Used to trigger side effects
- Example: logging, updating cache, recalculating derived values
3. show_hook
This hook customizes how the value is displayed when users run:
SHOW parameter_name;
Step 1: Define a Custom GUC Parameter
Note : we are using postgres version 19 (development phase source code).Only this version has the file named guc_parameters.dat and below version 19 you can set these in the file named guc_tables.c
Inside the guc_parameters.dat file , based on the alphabetical order add this parameter.
{ name => 'my_custom_value', type => 'int', context => 'PGC_SIGHUP', group => 'CUSTOM_OPTIONS',
short_desc => 'example configuration for understanding the purpose of different types of hooks',
long_desc => 'useful for understand the purpose of three types of hooks named check hooks,assign hooks and show hooks',
flags => '0',
variable => 'my_custom_value',
boot_val => '0',
min => '0',
max => '1000',
check_hook => 'check_my_custom_value',
assign_hook => 'assign_my_custom_value',
show_hook => 'show_my_custom_value',
},Here we specify the context for this parameter. Here the context specifies when and who is allowed to change a PostgreSQL configuration parameter. It helps control whether a setting can be modified at server start, on reload, or during a session.
Each level defines a different restriction, ranging from fixed internal settings to values that any user can change at runtime.
Here we define three separate functions for these three hooks to understand how these hooks are working inside postgres
Step 2: Implement Hook Functions
Create a C file:
Path: src/backend/utils/misc/my_custom.c
#include "postgres.h"
#include "utils/guc.h"
#include "utils/my_custom.h"
int my_custom_value = 0; /* default value */
check_hook Implementation
bool
check_my_custom_value(int *newval, void **extra, GucSource source)
{
if (*newval % 2 != 0)
{
GUC_check_errmsg("my_custom_value must be an even number");
return false;
}
return true;
}
Behavior:
- Only even numbers are allowed
- Odd numbers are rejected
This is just a basic functionality where it checks a simple validation for the custom parameter we implemented.
assign_hook Implementation
voidassign_my_custom_value(int newval, void *extra){ ereport(LOG, errmsg("my_custom_value assigned: %d", newval));}Behavior:
- Logs whenever a valid value is applied
- Called after validation
show_hook Implementation
const char *
show_my_custom_value(void)
{
char *buf = (char *) palloc(32);
snprintf(buf, 32, "%d (custom)", my_custom_value);
return buf;
}
Behavior:
- Modifies display output
- Adds "(custom)" to the value
Step 3: Header File
Path: src/include/utils/my_custom.h
Add the below code to this header file
#ifndef MY_CUSTOM_H
#define MY_CUSTOM_H
#include "utils/guc.h"
extern int my_custom_value;
extern bool check_my_custom_value(int *newval, void **extra, GucSource source);
extern void assign_my_custom_value(int newval, void *extra);
extern const char *show_my_custom_value(void);
#endif
In this header file, we declare the hook functions and the custom configuration variable. These declarations make them visible to other source files, while their actual implementations are defined in the corresponding .c file.
Step 4: Add File to Makefile
Inside the Makefile:
OBJS = \
conffiles.o \
guc.o \
guc-file.o \
guc_funcs.o \
guc_tables.o \
help_config.o \
injection_point.o \
pg_config.o \
pg_controldata.o \
pg_rusage.o \
ps_status.o \
queryenvironment.o \
rls.o \
sampling.o \
stack_depth.o \
superuser.o \
timeout.o \
tzparser.o \
My_custom.o
Step 5: Include Header in guc_tables.c
#include "utils/my_custom.h"
If you do not include the header file in guc_tables.c, you get compilation errors like invalid variable declaration.
Step 6: Compile the postgres source code
make
sudo make install
bin/pg_ctl -D cluster_name -l logfile -o "-p 5433" restart
bin/psql postgres -p 5433
Step 7: Testing in PostgreSQL
After building and running PostgreSQL:
SHOW my_custom_value;
Output:
my_custom_value
-----------------
0 (custom)
(1 row)
This confirms the show_hook is working.
Attempt to Set Invalid Value
SET my_custom_value = 1;
Output:
ERROR: parameter "my_custom_value" cannot be changed now
Reason:
- Context is PGC_SIGHUP, so SET is not allowed.
Using ALTER SYSTEM with Invalid Value
ALTER SYSTEM SET my_custom_value = 1;
Output:
ERROR: my_custom_value must be an even number
This confirms the check_hook is working correctly.
Using Valid Value
ALTER SYSTEM SET my_custom_value = 2;
Output:
ALTER SYSTEM
Reload Configuration
SELECT pg_reload_conf();
Observed Logs
Check the log file like this
tail -f logfile
After reload:
2026-05-05 19:42:49.713 IST [1361934] LOG: received SIGHUP, reloading configuration files
2026-05-05 19:42:49.714 IST [1361934] LOG: my_custom_value assigned: 2
2026-05-05 19:42:49.715 IST [1361942] LOG: my_custom_value assigned: 2
2026-05-05 19:42:49.715 IST [1361941] LOG: my_custom_value assigned: 2
2026-05-05 19:42:49.716 IST [1361937] LOG: my_custom_value assigned: 2
Key Observations:
- assign_hook is triggered multiple times
- Each backend process applies the new value
- This explains why logs appear repeatedly
From this implementation, you can clearly understand:
- check_hook ensures only valid values are accepted
- assign_hook executes logic when a value is applied
- show_hook customizes how values are displayed
When to Use These Hooks
Use these hooks when:
- You need strict validation rules
- You want to trigger internal logic when config changes
- You want user-friendly display formatting
GUC hooks provide deep control over PostgreSQL configuration behavior. Instead of just storing values, you can enforce rules, trigger logic, and customize outputs.
This example demonstrated a complete working implementation using:
- Custom integer parameter
- Even-number validation
- Logging on assignment
- Custom display formatting
Once you understand these hooks, you can extend PostgreSQL configuration to match complex application requirements, especially in performance tuning, feature toggling, and internal debugging.