--- title: "Server Programming" id: server-programming pg_version: "20devel" --- Part V. Server ProgrammingThis part is about extending the server functionality with user-defined functions, data types, triggers, etc. These are advanced topics which should be approached only after all the other user documentation about PostgreSQL has been understood. Later chapters in this part describe the server-side programming languages available in the PostgreSQL distribution as well as general issues concerning server-side programming. It is essential to read at least the earlier sections of [Chapter 36](extend.md) (covering functions) before diving into the material about server-side programming. ## Table of Contents - [36. Extending SQL](extend.md) - [36.1. How Extensibility Works](extend-how.md) - [36.2. The PostgreSQL Type System](extend-type-system.md) - [36.2.1. Base Types](extend-type-system.md#extend-type-system-base) - [36.2.2. Container Types](extend-type-system.md#extend-type-system-container) - [36.2.3. Domains](extend-type-system.md#extend-type-system-domains) - [36.2.4. Pseudo-Types](extend-type-system.md#extend-type-system-pseudo) - [36.2.5. Polymorphic Types](extend-type-system.md#extend-types-polymorphic) - [36.3. User-Defined Functions](xfunc.md) - [36.4. User-Defined Procedures](xproc.md) - [36.5. Query Language (SQL) Functions](xfunc-sql.md) - [36.5.1. Arguments for SQL Functions](xfunc-sql.md#xfunc-sql-function-arguments) - [36.5.2. SQL Functions on Base Types](xfunc-sql.md#xfunc-sql-base-functions) - [36.5.3. SQL Functions on Composite Types](xfunc-sql.md#xfunc-sql-composite-functions) - [36.5.4. SQL Functions with Output Parameters](xfunc-sql.md#xfunc-output-parameters) - [36.5.5. SQL Procedures with Output Parameters](xfunc-sql.md#xfunc-output-parameters-proc) - [36.5.6. SQL Functions with Variable Numbers of Arguments](xfunc-sql.md#xfunc-sql-variadic-functions) - [36.5.7. SQL Functions with Default Values for Arguments](xfunc-sql.md#xfunc-sql-parameter-defaults) - [36.5.8. SQL Functions as Table Sources](xfunc-sql.md#xfunc-sql-table-functions) - [36.5.9. SQL Functions Returning Sets](xfunc-sql.md#xfunc-sql-functions-returning-set) - [36.5.10. SQL Functions Returning `TABLE`](xfunc-sql.md#xfunc-sql-functions-returning-table) - [36.5.11. Polymorphic SQL Functions](xfunc-sql.md#xfunc-sql-polymorphic-functions) - [36.5.12. SQL Functions with Collations](xfunc-sql.md#xfunc-sql-collations) - [36.6. Function Overloading](xfunc-overload.md) - [36.7. Function Volatility Categories](xfunc-volatility.md) - [36.8. Procedural Language Functions](xfunc-pl.md) - [36.9. Internal Functions](xfunc-internal.md) - [36.10. C-Language Functions](xfunc-c.md) - [36.10.1. Dynamic Loading](xfunc-c.md#xfunc-c-dynload) - [36.10.2. Base Types in C-Language Functions](xfunc-c.md#xfunc-c-basetype) - [36.10.3. Version 1 Calling Conventions](xfunc-c.md#xfunc-c-v1-call-conv) - [36.10.4. Writing Code](xfunc-c.md#xfunc-c-code) - [36.10.5. Compiling and Linking Dynamically-Loaded Functions](xfunc-c.md#dfunc) - [36.10.6. Server API and ABI Stability Guidance](xfunc-c.md#xfunc-api-abi-stability-guidance) - [36.10.7. Composite-Type Arguments](xfunc-c.md#xfunc-c-composite-type-args) - [36.10.8. Returning Rows (Composite Types)](xfunc-c.md#xfunc-c-returning-rows) - [36.10.9. Returning Sets](xfunc-c.md#xfunc-c-return-set) - [36.10.10. Polymorphic Arguments and Return Types](xfunc-c.md#xfunc-c-polymorphic) - [36.10.11. Shared Memory](xfunc-c.md#xfunc-shared-addin) - [36.10.12. LWLocks](xfunc-c.md#xfunc-addin-lwlocks) - [36.10.13. Custom Wait Events](xfunc-c.md#xfunc-addin-wait-events) - [36.10.14. Injection Points](xfunc-c.md#xfunc-addin-injection-points) - [36.10.15. Custom Cumulative Statistics](xfunc-c.md#xfunc-addin-custom-cumulative-statistics) - [36.10.16. Using C++ for Extensibility](xfunc-c.md#extend-cpp) - [36.11. Function Optimization Information](xfunc-optimization.md) - [36.12. User-Defined Aggregates](xaggr.md) - [36.12.1. Moving-Aggregate Mode](xaggr.md#xaggr-moving-aggregates) - [36.12.2. Polymorphic and Variadic Aggregates](xaggr.md#xaggr-polymorphic-aggregates) - [36.12.3. Ordered-Set Aggregates](xaggr.md#xaggr-ordered-set-aggregates) - [36.12.4. Partial Aggregation](xaggr.md#xaggr-partial-aggregates) - [36.12.5. Support Functions for Aggregates](xaggr.md#xaggr-support-functions) - [36.13. User-Defined Types](xtypes.md) - [36.13.1. TOAST Considerations](xtypes.md#xtypes-toast) - [36.14. User-Defined Operators](xoper.md) - [36.15. Operator Optimization Information](xoper-optimization.md) - [36.15.1. `COMMUTATOR`](xoper-optimization.md#xoper-commutator) - [36.15.2. `NEGATOR`](xoper-optimization.md#xoper-negator) - [36.15.3. `RESTRICT`](xoper-optimization.md#xoper-restrict) - [36.15.4. `JOIN`](xoper-optimization.md#xoper-join) - [36.15.5. `HASHES`](xoper-optimization.md#xoper-hashes) - [36.15.6. `MERGES`](xoper-optimization.md#xoper-merges) - [36.16. Interfacing Extensions to Indexes](xindex.md) - [36.16.1. Index Methods and Operator Classes](xindex.md#xindex-opclass) - [36.16.2. Index Method Strategies](xindex.md#xindex-strategies) - [36.16.3. Index Method Support Routines](xindex.md#xindex-support) - [36.16.4. An Example](xindex.md#xindex-example) - [36.16.5. Operator Classes and Operator Families](xindex.md#xindex-opfamily) - [36.16.6. System Dependencies on Operator Classes](xindex.md#xindex-opclass-dependencies) - [36.16.7. Ordering Operators](xindex.md#xindex-ordering-ops) - [36.16.8. Special Features of Operator Classes](xindex.md#xindex-opclass-features) - [36.17. Packaging Related Objects into an Extension](extend-extensions.md) - [36.17.1. Extension Files](extend-extensions.md#extend-extensions-files) - [36.17.2. Extension Relocatability](extend-extensions.md#extend-extensions-relocation) - [36.17.3. Extension Configuration Tables](extend-extensions.md#extend-extensions-config-tables) - [36.17.4. Extension Updates](extend-extensions.md#extend-extensions-updates) - [36.17.5. Installing Extensions Using Update Scripts](extend-extensions.md#extend-extensions-update-scripts) - [36.17.6. Security Considerations for Extensions](extend-extensions.md#extend-extensions-security) - [36.17.7. Extension Example](extend-extensions.md#extend-extensions-example) - [36.18. Extension Building Infrastructure](extend-pgxs.md) - [37. Triggers](triggers.md) - [37.1. Overview of Trigger Behavior](trigger-definition.md) - [37.2. Visibility of Data Changes](trigger-datachanges.md) - [37.3. Writing Trigger Functions in C](trigger-interface.md) - [37.4. A Complete Trigger Example](trigger-example.md) - [38. Event Triggers](event-triggers.md) - [38.1. Overview of Event Trigger Behavior](event-trigger-definition.md) - [38.1.1. login](event-trigger-definition.md#event-trigger-login) - [38.1.2. ddl_command_start](event-trigger-definition.md#event-trigger-ddl_command_start) - [38.1.3. ddl_command_end](event-trigger-definition.md#event-trigger-ddl_command_end) - [38.1.4. sql_drop](event-trigger-definition.md#event-trigger-sql_drop) - [38.1.5. table_rewrite](event-trigger-definition.md#event-trigger-table_rewrite) - [38.1.6. Event Triggers in Aborted Transactions](event-trigger-definition.md#event-trigger-aborted-transactions) - [38.1.7. Creating Event Triggers](event-trigger-definition.md#event-trigger-creating) - [38.2. Writing Event Trigger Functions in C](event-trigger-interface.md) - [38.3. A Complete Event Trigger Example](event-trigger-example.md) - [38.4. A Table Rewrite Event Trigger Example](event-trigger-table-rewrite-example.md) - [38.5. A Database Login Event Trigger Example](event-trigger-database-login-example.md) - [39. The Rule System](rules.md) - [39.1. The Query Tree](querytree.md) - [39.2. Views and the Rule System](rules-views.md) - [39.2.1. How `SELECT` Rules Work](rules-views.md#rules-select) - [39.2.2. View Rules in Non-`SELECT` Statements](rules-views.md#rules-views-non-select) - [39.2.3. The Power of Views in PostgreSQL](rules-views.md#rules-views-power) - [39.2.4. Updating a View](rules-views.md#rules-views-update) - [39.3. Materialized Views](rules-materializedviews.md) - [39.4. Rules on `INSERT`, `UPDATE`, and `DELETE`](rules-update.md) - [39.4.1. How Update Rules Work](rules-update.md#rules-update-how) - [39.4.2. Cooperation with Views](rules-update.md#rules-update-views) - [39.5. Rules and Privileges](rules-privileges.md) - [39.6. Rules and Command Status](rules-status.md) - [39.7. Rules Versus Triggers](rules-triggers.md) - [40. Procedural Languages](xplang.md) - [40.1. Installing Procedural Languages](xplang-install.md) - [41. PL/pgSQL — SQL Procedural Language](plpgsql.md) - [41.1. Overview](plpgsql-overview.md) - [41.1.1. Advantages of Using PL/pgSQL](plpgsql-overview.md#plpgsql-advantages) - [41.1.2. Supported Argument and Result Data Types](plpgsql-overview.md#plpgsql-args-results) - [41.2. Structure of PL/pgSQL](plpgsql-structure.md) - [41.3. Declarations](plpgsql-declarations.md) - [41.3.1. Declaring Function Parameters](plpgsql-declarations.md#plpgsql-declaration-parameters) - [41.3.2. `ALIAS`](plpgsql-declarations.md#plpgsql-declaration-alias) - [41.3.3. Copying Types](plpgsql-declarations.md#plpgsql-declaration-type) - [41.3.4. Row Types](plpgsql-declarations.md#plpgsql-declaration-rowtypes) - [41.3.5. Record Types](plpgsql-declarations.md#plpgsql-declaration-records) - [41.3.6. Collation of PL/pgSQL Variables](plpgsql-declarations.md#plpgsql-declaration-collation) - [41.4. Expressions](plpgsql-expressions.md) - [41.5. Basic Statements](plpgsql-statements.md) - [41.5.1. Assignment](plpgsql-statements.md#plpgsql-statements-assignment) - [41.5.2. Executing SQL Commands](plpgsql-statements.md#plpgsql-statements-general-sql) - [41.5.3. Executing a Command with a Single-Row Result](plpgsql-statements.md#plpgsql-statements-sql-onerow) - [41.5.4. Executing Dynamic Commands](plpgsql-statements.md#plpgsql-statements-executing-dyn) - [41.5.5. Obtaining the Result Status](plpgsql-statements.md#plpgsql-statements-diagnostics) - [41.5.6. Doing Nothing At All](plpgsql-statements.md#plpgsql-statements-null) - [41.6. Control Structures](plpgsql-control-structures.md) - [41.6.1. Returning from a Function](plpgsql-control-structures.md#plpgsql-statements-returning) - [41.6.2. Returning from a Procedure](plpgsql-control-structures.md#plpgsql-statements-returning-procedure) - [41.6.3. Calling a Procedure](plpgsql-control-structures.md#plpgsql-statements-calling-procedure) - [41.6.4. Conditionals](plpgsql-control-structures.md#plpgsql-conditionals) - [41.6.5. Simple Loops](plpgsql-control-structures.md#plpgsql-control-structures-loops) - [41.6.6. Looping through Query Results](plpgsql-control-structures.md#plpgsql-records-iterating) - [41.6.7. Looping through Arrays](plpgsql-control-structures.md#plpgsql-foreach-array) - [41.6.8. Trapping Errors](plpgsql-control-structures.md#plpgsql-error-trapping) - [41.6.9. Obtaining Execution Location Information](plpgsql-control-structures.md#plpgsql-call-stack) - [41.7. Cursors](plpgsql-cursors.md) - [41.7.1. Declaring Cursor Variables](plpgsql-cursors.md#plpgsql-cursor-declarations) - [41.7.2. Opening Cursors](plpgsql-cursors.md#plpgsql-cursor-opening) - [41.7.3. Using Cursors](plpgsql-cursors.md#plpgsql-cursor-using) - [41.7.4. Looping through a Cursor's Result](plpgsql-cursors.md#plpgsql-cursor-for-loop) - [41.8. Transaction Management](plpgsql-transactions.md) - [41.9. Errors and Messages](plpgsql-errors-and-messages.md) - [41.9.1. Reporting Errors and Messages](plpgsql-errors-and-messages.md#plpgsql-statements-raise) - [41.9.2. Checking Assertions](plpgsql-errors-and-messages.md#plpgsql-statements-assert) - [41.10. Trigger Functions](plpgsql-trigger.md) - [41.10.1. Triggers on Data Changes](plpgsql-trigger.md#plpgsql-dml-trigger) - [41.10.2. Triggers on Events](plpgsql-trigger.md#plpgsql-event-trigger) - [41.11. PL/pgSQL under the Hood](plpgsql-implementation.md) - [41.11.1. Variable Substitution](plpgsql-implementation.md#plpgsql-var-subst) - [41.11.2. Plan Caching](plpgsql-implementation.md#plpgsql-plan-caching) - [41.12. Tips for Developing in PL/pgSQL](plpgsql-development-tips.md) - [41.12.1. Handling of Quotation Marks](plpgsql-development-tips.md#plpgsql-quote-tips) - [41.12.2. Additional Compile-Time and Run-Time Checks](plpgsql-development-tips.md#plpgsql-extra-checks) - [41.13. Porting from Oracle PL/SQL](plpgsql-porting.md) - [41.13.1. Porting Examples](plpgsql-porting.md#plpgsql-porting-examples) - [41.13.2. Other Things to Watch For](plpgsql-porting.md#plpgsql-porting-other) - [41.13.3. Appendix](plpgsql-porting.md#plpgsql-porting-appendix) - [42. PL/Tcl — Tcl Procedural Language](pltcl.md) - [42.1. Overview](pltcl-overview.md) - [42.2. PL/Tcl Functions and Arguments](pltcl-functions.md) - [42.3. Data Values in PL/Tcl](pltcl-data.md) - [42.4. Global Data in PL/Tcl](pltcl-global.md) - [42.5. Database Access from PL/Tcl](pltcl-dbaccess.md) - [42.6. Trigger Functions in PL/Tcl](pltcl-trigger.md) - [42.7. Event Trigger Functions in PL/Tcl](pltcl-event-trigger.md) - [42.8. Error Handling in PL/Tcl](pltcl-error-handling.md) - [42.9. Explicit Subtransactions in PL/Tcl](pltcl-subtransactions.md) - [42.10. Transaction Management](pltcl-transactions.md) - [42.11. PL/Tcl Configuration](pltcl-config.md) - [42.12. Tcl Procedure Names](pltcl-procnames.md) - [43. PL/Perl — Perl Procedural Language](plperl.md) - [43.1. PL/Perl Functions and Arguments](plperl-funcs.md) - [43.2. Data Values in PL/Perl](plperl-data.md) - [43.3. Built-in Functions](plperl-builtins.md) - [43.3.1. Database Access from PL/Perl](plperl-builtins.md#plperl-database) - [43.3.2. Utility Functions in PL/Perl](plperl-builtins.md#plperl-utility-functions) - [43.4. Global Values in PL/Perl](plperl-global.md) - [43.5. Trusted and Untrusted PL/Perl](plperl-trusted.md) - [43.6. PL/Perl Triggers](plperl-triggers.md) - [43.7. PL/Perl Event Triggers](plperl-event-triggers.md) - [43.8. PL/Perl Under the Hood](plperl-under-the-hood.md) - [43.8.1. Configuration](plperl-under-the-hood.md#plperl-config) - [43.8.2. Limitations and Missing Features](plperl-under-the-hood.md#plperl-missing) - [44. PL/Python — Python Procedural Language](plpython.md) - [44.1. PL/Python Functions](plpython-funcs.md) - [44.2. Data Values](plpython-data.md) - [44.2.1. Data Type Mapping](plpython-data.md#plpython-data-type-mapping) - [44.2.2. Null, None](plpython-data.md#plpython-data-null) - [44.2.3. Arrays, Lists](plpython-data.md#plpython-arrays) - [44.2.4. Composite Types](plpython-data.md#plpython-data-composite-types) - [44.2.5. Set-Returning Functions](plpython-data.md#plpython-data-set-returning-funcs) - [44.3. Sharing Data](plpython-sharing.md) - [44.4. Anonymous Code Blocks](plpython-do.md) - [44.5. Trigger Functions](plpython-trigger.md) - [44.6. Event Trigger Functions](plpython-event-trigger.md) - [44.7. Database Access](plpython-database.md) - [44.7.1. Database Access Functions](plpython-database.md#plpython-database-access-funcs) - [44.7.2. Trapping Errors](plpython-database.md#plpython-trapping) - [44.8. Explicit Subtransactions](plpython-subtransaction.md) - [44.8.1. Subtransaction Context Managers](plpython-subtransaction.md#plpython-subtransaction-context-managers) - [44.9. Transaction Management](plpython-transactions.md) - [44.10. Utility Functions](plpython-util.md) - [44.11. Python 2 vs. Python 3](plpython-python23.md) - [44.12. Environment Variables](plpython-envar.md) - [45. Server Programming Interface](spi.md) - [45.1. Interface Functions](spi-interface.md) - [SPI_connect](spi-spi-connect.md) - [SPI_finish](spi-spi-finish.md) - [SPI_execute](spi-spi-execute.md) - [SPI_exec](spi-spi-exec.md) - [SPI_execute_extended](spi-spi-execute-extended.md) - [SPI_execute_with_args](spi-spi-execute-with-args.md) - [SPI_prepare](spi-spi-prepare.md) - [SPI_prepare_cursor](spi-spi-prepare-cursor.md) - [SPI_prepare_extended](spi-spi-prepare-extended.md) - [SPI_prepare_params](spi-spi-prepare-params.md) - [SPI_getargcount](spi-spi-getargcount.md) - [SPI_getargtypeid](spi-spi-getargtypeid.md) - [SPI_is_cursor_plan](spi-spi-is-cursor-plan.md) - [SPI_execute_plan](spi-spi-execute-plan.md) - [SPI_execute_plan_extended](spi-spi-execute-plan-extended.md) - [SPI_execute_plan_with_paramlist](spi-spi-execute-plan-with-paramlist.md) - [SPI_execp](spi-spi-execp.md) - [SPI_cursor_open](spi-spi-cursor-open.md) - [SPI_cursor_open_with_args](spi-spi-cursor-open-with-args.md) - [SPI_cursor_open_with_paramlist](spi-spi-cursor-open-with-paramlist.md) - [SPI_cursor_parse_open](spi-spi-cursor-parse-open.md) - [SPI_cursor_find](spi-spi-cursor-find.md) - [SPI_cursor_fetch](spi-spi-cursor-fetch.md) - [SPI_cursor_move](spi-spi-cursor-move.md) - [SPI_scroll_cursor_fetch](spi-spi-scroll-cursor-fetch.md) - [SPI_scroll_cursor_move](spi-spi-scroll-cursor-move.md) - [SPI_cursor_close](spi-spi-cursor-close.md) - [SPI_keepplan](spi-spi-keepplan.md) - [SPI_saveplan](spi-spi-saveplan.md) - [SPI_register_relation](spi-spi-register-relation.md) - [SPI_unregister_relation](spi-spi-unregister-relation.md) - [SPI_register_trigger_data](spi-spi-register-trigger-data.md) - [45.2. Interface Support Functions](spi-interface-support.md) - [SPI_fname](spi-spi-fname.md) - [SPI_fnumber](spi-spi-fnumber.md) - [SPI_getvalue](spi-spi-getvalue.md) - [SPI_getbinval](spi-spi-getbinval.md) - [SPI_gettype](spi-spi-gettype.md) - [SPI_gettypeid](spi-spi-gettypeid.md) - [SPI_getrelname](spi-spi-getrelname.md) - [SPI_getnspname](spi-spi-getnspname.md) - [SPI_result_code_string](spi-spi-result-code-string.md) - [45.3. Memory Management](spi-memory.md) - [SPI_palloc](spi-spi-palloc.md) - [SPI_repalloc](spi-realloc.md) - [SPI_pfree](spi-spi-pfree.md) - [SPI_copytuple](spi-spi-copytuple.md) - [SPI_returntuple](spi-spi-returntuple.md) - [SPI_modifytuple](spi-spi-modifytuple.md) - [SPI_freetuple](spi-spi-freetuple.md) - [SPI_freetuptable](spi-spi-freetupletable.md) - [SPI_freeplan](spi-spi-freeplan.md) - [45.4. Transaction Management](spi-transaction.md) - [SPI_commit](spi-spi-commit.md) - [SPI_rollback](spi-spi-rollback.md) - [SPI_start_transaction](spi-spi-start-transaction.md) - [45.5. Visibility of Data Changes](spi-visibility.md) - [45.6. Examples](spi-examples.md) - [46. Background Worker Processes](bgworker.md) - [47. Logical Decoding](logicaldecoding.md) - [47.1. Logical Decoding Examples](logicaldecoding-example.md) - [47.2. Logical Decoding Concepts](logicaldecoding-explanation.md) - [47.2.1. Logical Decoding](logicaldecoding-explanation.md#logicaldecoding-explanation-log-dec) - [47.2.2. Replication Slots](logicaldecoding-explanation.md#logicaldecoding-replication-slots) - [47.2.3. Replication Slot Synchronization](logicaldecoding-explanation.md#logicaldecoding-replication-slots-synchronization) - [47.2.4. Output Plugins](logicaldecoding-explanation.md#logicaldecoding-explanation-output-plugins) - [47.2.5. Exported Snapshots](logicaldecoding-explanation.md#logicaldecoding-explanation-exported-snapshots) - [47.3. Streaming Replication Protocol Interface](logicaldecoding-walsender.md) - [47.4. Logical Decoding SQL Interface](logicaldecoding-sql.md) - [47.5. System Catalogs Related to Logical Decoding](logicaldecoding-catalogs.md) - [47.6. Logical Decoding Output Plugins](logicaldecoding-output-plugin.md) - [47.6.1. pgoutput — Standard Logical Decoding Output Plugin](logicaldecoding-output-plugin.md#logicaldecoding-pgoutput) - [47.7. Writing Logical Decoding Output Plugins](logicaldecoding-output-plugin-writing.md) - [47.7.1. Initialization Function](logicaldecoding-output-plugin-writing.md#logicaldecoding-output-init) - [47.7.2. Capabilities](logicaldecoding-output-plugin-writing.md#logicaldecoding-capabilities) - [47.7.3. Output Modes](logicaldecoding-output-plugin-writing.md#logicaldecoding-output-mode) - [47.7.4. Output Plugin Callbacks](logicaldecoding-output-plugin-writing.md#logicaldecoding-output-plugin-callbacks) - [47.7.5. Functions for Producing Output](logicaldecoding-output-plugin-writing.md#logicaldecoding-output-plugin-output) - [47.8. Logical Decoding Output Writers](logicaldecoding-writer.md) - [47.9. Synchronous Replication Support for Logical Decoding](logicaldecoding-synchronous.md) - [47.9.1. Overview](logicaldecoding-synchronous.md#logicaldecoding-synchronous-overview) - [47.9.2. Caveats](logicaldecoding-synchronous.md#logicaldecoding-synchronous-caveats) - [47.10. Streaming of Large Transactions for Logical Decoding](logicaldecoding-streaming.md) - [47.11. Two-phase Commit Support for Logical Decoding](logicaldecoding-two-phase-commits.md) - [48. Replication Progress Tracking](replication-origins.md) - [49. Archive Modules](archive-modules.md) - [49.1. Initialization Functions](archive-module-init.md) - [49.2. Archive Module Callbacks](archive-module-callbacks.md) - [49.2.1. Startup Callback](archive-module-callbacks.md#archive-module-startup) - [49.2.2. Check Callback](archive-module-callbacks.md#archive-module-check) - [49.2.3. Archive Callback](archive-module-callbacks.md#archive-module-archive) - [49.2.4. Shutdown Callback](archive-module-callbacks.md#archive-module-shutdown) - [50. OAuth Validator Modules](oauth-validators.md) - [50.1. Safely Designing a Validator Module](oauth-validator-design.md) - [50.1.1. Validator Responsibilities](oauth-validator-design.md#oauth-validator-design-responsibilities) - [50.1.2. General Coding Guidelines](oauth-validator-design.md#oauth-validator-design-guidelines) - [50.1.3. Authorizing Users (Usermap Delegation)](oauth-validator-design.md#oauth-validator-design-usermap-delegation) - [50.2. Initialization Functions](oauth-validator-init.md) - [50.3. OAuth Validator Callbacks](oauth-validator-callbacks.md) - [50.3.1. Startup Callback](oauth-validator-callbacks.md#oauth-validator-callback-startup) - [50.3.2. Validate Callback](oauth-validator-callbacks.md#oauth-validator-callback-validate) - [50.3.3. Shutdown Callback](oauth-validator-callbacks.md#oauth-validator-callback-shutdown) - [50.4. Custom HBA Options](oauth-validator-hba.md) - [50.4.1. Options API](oauth-validator-hba.md#oauth-validator-hba-api) - [50.4.2. Limitations](oauth-validator-hba.md#oauth-validator-hba-limitations) - [50.4.3. Example Usage](oauth-validator-hba.md#oauth-validator-hba-example-usage)