How to Create Custom Configuration Parameters in PostgreSQL 19devel

PostgreSQL provides a powerful configuration system called GUC (Grand Unified Configuration). It is the internal framework that manages all runtime parameters such as shared_buffers, work_mem, log_statement, and many others. If you are working with the PostgreSQL source code, learning how to add your own custom configuration parameter is an excellent way to understand the internals of the database engine.

Why Learn Custom Configuration Parameters

Adding a custom parameter helps you understand:

  • How PostgreSQL stores runtime settings
  • How parameters are generated from metadata
  • How GUC contexts work
  • How PostgreSQL integrates source code variables with SQL-visible settings
  • How to extend PostgreSQL for custom features

This is useful for contributors, database engineers, and developers building customized PostgreSQL distributions.

Add the Parameter in guc_parameters.dat

In PostgreSQL 19, configuration parameters are defined in a metadata file instead of being manually written into source arrays. This file is:

src/backend/utils/misc/guc_parameters.dat

Add the following entry:

{ name => 'custom_log_enabled', type => 'bool', context => 'PGC_USERSET', group => 'CUSTOM_OPTIONS',
  short_desc => 'A custom postgres configuration parameter for learning the way of implementing it in latest postgres source code',
  flags => '0',
  variable => 'custom_log_enabled',
  boot_val => 'false',
},

Understanding Each Field

name => 'custom_log_enabled'

This is the SQL-visible parameter name.

You will use it like this:

SHOW custom_log_enabled;
SET custom_log_enabled = on;

type => 'bool'

This defines the data type.

Since we are using a boolean type, PostgreSQL accepts:

on / off
true / false
1 / 0
yes / no

context => 'PGC_USERSET'

This defines who can change the parameter and when it can be changed.

PostgreSQL supports multiple parameter contexts:

typedef enum
{
    PGC_INTERNAL,
    PGC_POSTMASTER,
    PGC_SIGHUP,
    PGC_SU_BACKEND,
    PGC_BACKEND,
    PGC_SUSET,
    PGC_USERSET,
} GucContext;

Meaning of Important Contexts

  • PGC_INTERNAL: Internal only. Users cannot modify it.
  • PGC_POSTMASTER: Requires server restart.
  • PGC_SIGHUP: Change in config file + reload.
  • PGC_SUSET: Only superusers can change it.
  • PGC_USERSET: Any user can change it anytime.

We selected:

PGC_USERSET

So anyone can modify it during a session.

group => 'CUSTOM_OPTIONS'

This decides where the parameter appears in configuration views.

Available groups include categories such as memory, WAL, logging, vacuum, replication, and custom options.

PostgreSQL internally defines groups like:

CUSTOM_OPTIONS
DEVELOPER_OPTIONS
LOGGING_WHAT
WAL_SETTINGS
RESOURCES_MEM
VACUUM_AUTOVACUUM

We used:

CUSTOM_OPTIONS

So it appears under:

Customized Options

In postgres there are nearly 48 categories for the postgres configuration parameters

postgres=# select distinct(category) from pg_settings ;
                             category                              
-------------------------------------------------------------------
 Connections and Authentication / TCP Settings
 Version and Platform Compatibility / Other Platforms and Clients
 Vacuuming / Automatic Vacuuming
 Query Tuning / Planner Method Configuration
 Query Tuning / Other Planner Options
 Client Connection Defaults / Statement Behavior
 File Locations
 Write-Ahead Log / Settings
 Client Connection Defaults / Shared Library Preloading
 Replication / Subscribers
 Client Connection Defaults / Locale and Formatting
 Reporting and Logging / What to Log
 Write-Ahead Log / Checkpoints
 Reporting and Logging / When to Log
 Resource Usage / Background Writer
 Resource Usage / I/O
 Write-Ahead Log / Recovery Target
 Error Handling
 Resource Usage / Disk
 Query Tuning / Genetic Query Optimizer
 Preset Options
 Statistics / Monitoring
 Resource Usage / Time
 Resource Usage / Kernel Resources
 Statistics / Cumulative Query and Index Statistics
 Lock Management
 Customized Options
 Resource Usage / Memory
 Replication / Sending Servers
 Version and Platform Compatibility / Previous PostgreSQL Versions
 Write-Ahead Log / Archive Recovery
 Resource Usage / Worker Processes
 Developer Options
 Write-Ahead Log / Summarization
 Write-Ahead Log / Archiving
 Replication / Primary Server
 Connections and Authentication / Authentication
 Write-Ahead Log / Recovery
 Vacuuming / Cost-Based Vacuum Delay
 Replication / Standby Servers
 Connections and Authentication / SSL
 Reporting and Logging / Process Title
 Client Connection Defaults / Other Defaults
 Query Tuning / Planner Cost Constants
 Connections and Authentication / Connection Settings
 Vacuuming / Default Behavior
 Vacuuming / Freezing
 Reporting and Logging / Where to Log
(48 rows)

short_desc

This description is shown in pg_settings.

short_desc => 'A custom postgres configuration parameter for learning the way of implementing it in latest postgres source code'

flags => '0'

Flags modify parameter behavior.

PostgreSQL supports flags such as:

GUC_REPORT
GUC_NO_SHOW_ALL
GUC_SUPERUSER_ONLY
GUC_NOT_IN_SAMPLE
GUC_ALLOW_IN_PARALLEL

Since we do not need any special behavior, we use:

flags => '0'

variable => 'custom_log_enabled'

This links the configuration parameter to a C global variable.

boot_val => 'false'

This is the default value when PostgreSQL starts.

Important Note: Keep Alphabetical Order

When adding a new entry in guc_parameters.dat, place it in the correct alphabetical order.

For example:

custom_log_enabled

must be inserted in the proper sorted location.

If not, PostgreSQL may fail during code generation or compilation.

Create the Header File

Create a new header file:

src/include/utils/custom_logs.h

Add:

#ifndef CUSTOM_LOGS_H
#define CUSTOM_LOGS_H
extern bool custom_log_enabled;
extern void enable_custom_logs(void);
#endif /* CUSTOM_LOGS_H */

Here we use the extern keyword to specify the compiler that this boolean variable and this function is declared somewhere in source code

Purpose of Header Guards

These lines:

#ifndef CUSTOM_LOGS_H
#define CUSTOM_LOGS_H
...
#endif

prevent multiple inclusion of the same header file.

Without header guards, if the file is included more than once, compilation errors such as duplicate declarations can happen.

Header guards ensure the file is processed only once per compilation unit.

Create the Source File

Create:

src/backend/utils/misc/custom_log.c

Add:

#include "postgres.h"
#include "utils/custom_logs.h"
bool custom_log_enabled = false;
void enable_custom_logs(void)
{
    if(custom_log_enabled)
    {
        ereport(LOG,errmsg("Custom logs are enabled."));
    }
};

Code Explanation

Global Variable

bool custom_log_enabled = false;

This stores the current value of the parameter.

When PostgreSQL reads:

custom_log_enabled = on

the variable becomes:

true

Logging Function

enable_custom_logs()

This checks whether the parameter is enabled.

If true, PostgreSQL writes:

Custom logs are enabled.

to the server log.

Add the New Source File to the Makefile

Open the Makefile inside:

src/backend/utils/misc/Makefile

Add custom_log.o to the object list:

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 \
    custom_log.o

This ensures the new file is compiled and linked into PostgreSQL.

Include the Header File

Include the header in:

guc_tables.c
postinit.c

Add:

#include "utils/custom_logs.h"

Call the Function During Startup

Inside postinit.c, locate:

InitPostgres()

At the end of that function, add:

enable_custom_logs();

Now PostgreSQL will check the parameter whenever a backend initializes.

Rebuild PostgreSQL

After source changes:

make clean
make
sudo make install

Then restart the server.

Generated Code in PostgreSQL 19

You do not manually edit guc_tables.c.

PostgreSQL automatically generates internal code from guc_parameters.dat.

Your parameter becomes part of generated structures such as:

struct config_generic ConfigureNames[] =
{
    {
        .name = "custom_log_enabled",
        .context = PGC_USERSET,
        .group = CUSTOM_OPTIONS,
        .short_desc = gettext_noop("A custom postgres configuration parameter for learning the way of implementing it in latest postgres source code"),
        .vartype = PGC_BOOL,
        ._bool = {
            .variable = &custom_log_enabled,
            .boot_val = false,
        },
    },
};

This is one of the major architectural improvements in newer PostgreSQL versions.

Instead of manually maintaining large arrays, metadata now drives code generation.

Verify the Parameter in SQL

Run:

SHOW custom_log_enabled;

Output:

custom_log_enabled
--------------------
 off

Query pg_settings:

SELECT * FROM pg_settings WHERE name = 'custom_log_enabled';

Example output:

name            | custom_log_enabled
setting         | off
category        | Customized Options
short_desc      | A custom postgres configuration parameter for learning the way of implementing it in latest postgres source code
context         | user
vartype         | bool
source          | default
boot_val        | off
reset_val       | off
pending_restart | f

This confirms PostgreSQL fully recognizes your custom parameter.

Add it to postgresql.conf

Check config file path:

SHOW config_file;

Example:

/home/cybrosys/cybro_postgres/odoo_data/postgresql.conf

Now, add inside the customized options section:

#------------------------------------------------------------------------------
# CUSTOMIZED OPTIONS
#------------------------------------------------------------------------------
custom_log_enabled = 'on'
# Add settings for extensions here

Restart PostgreSQL

Restart the server:

bin/pg_ctl -D odoo_data/ -l logfile "-o -p 5440" restart

Connect:

bin/psql postgres -p 5440

Check the Log File

tail -f logfile

You should see:

2026-04-19 11:30:33.692 IST LOG: starting PostgreSQL 19devel ...
2026-04-19 11:30:33.705 IST LOG: database system is ready to accept connections
2026-04-19 11:30:52.795 IST LOG: Custom logs are enabled.

That means your custom configuration parameter successfully controlled internal PostgreSQL behavior.

The newer PostgreSQL architecture uses metadata-driven generation for GUC definitions. This reduces manual maintenance and keeps parameter definitions cleaner and more structured.

For developers working on PostgreSQL internals, understanding this design is extremely valuable.

Implementing a custom PostgreSQL configuration parameter is one of the best beginner-friendly ways to explore PostgreSQL source code internals. In PostgreSQL 19, the process is cleaner because parameter metadata is centralized in guc_parameters.dat, and internal code is generated automatically. By creating custom_log_enabled, connecting it to a C variable, and using it in backend startup logic, you built a real server-level feature that behaves like a native PostgreSQL setting. This knowledge creates a strong foundation for advanced customization such as performance tuning options, debugging switches, feature toggles, or entirely new database behaviors.

whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message