Skip to content
Written with Claude

NpgsqlRest Options

NpgsqlRest HTTP middleware general configuration for endpoint generation and request handling.

Overview

json
json
{
  "NpgsqlRest": {
    "ConnectionName": null,
    "UseMultipleConnections": false,
    "CommandTimeout": null,
    "SchemaSimilarTo": null,
    "SchemaNotSimilarTo": null,
    "IncludeSchemas": null,
    "ExcludeSchemas": null,
    "NameSimilarTo": null,
    "NameNotSimilarTo": null,
    "IncludeNames": null,
    "ExcludeNames": null,
    "CommentsMode": "OnlyWithHttpTag",
    "UrlPathPrefix": "/api",
    "KebabCaseUrls": true,
    "CamelCaseNames": true,
    "RequiresAuthorization": true,
    "LogConnectionNoticeEvents": true,
    "LogConnectionNoticeEventsMode": "FirstStackFrameAndMessage",
    "LogCommands": false,
    "LogCommandParameters": false,
    "DefaultHttpMethod": null,
    "DefaultRequestParamType": null,
    "RequestHeadersMode": "Parameter",
    "RequestHeadersContextKey": "request.headers",
    "RequestHeadersParameterName": "_headers",
    "InstanceIdRequestHeaderName": null,
    "CustomRequestHeaders": {},
    "ExecutionIdHeaderName": "X-NpgsqlRest-ID",
    "QueryStringNullHandling": "Ignore",
    "TextResponseNullHandling": "EmptyString",
    "DefaultServerSentEventsEventNoticeLevel": "INFO",
    "ServerSentEventsResponseHeaders": {},
    "RoutineOptions": { ... },
    "AuthenticationOptions": { ... },
    "SqlFileSource": { ... },
    "UploadOptions": { ... },
    "ClientCodeGen": { ... },
    "HttpFileOptions": { ... },
    "OpenApiOptions": { ... }
  }
}

See related configuration pages:

Connection Settings

SettingTypeDefaultDescription
ConnectionNamestringnullConnection name from ConnectionStrings section. Uses first available if null.
UseMultipleConnectionsboolfalseAllow individual routines to use different connections from ConnectionStrings.
CommandTimeoutstringnullCommand timeout using interval format (e.g., "30s", "1m"). Uses default 30 seconds if null. Can be overridden per endpoint with command_timeout annotation.

Schema and Name Filtering

Filter which PostgreSQL routines are exposed as endpoints.

SettingTypeDefaultDescription
SchemaSimilarTostringnullInclude schemas matching this SQL SIMILAR TO pattern.
SchemaNotSimilarTostringnullExclude schemas matching this SQL SIMILAR TO pattern.
IncludeSchemasarraynullList of schema names to include.
ExcludeSchemasarraynullList of schema names to exclude.
NameSimilarTostringnullInclude routine names matching this SQL SIMILAR TO pattern.
NameNotSimilarTostringnullExclude routine names matching this SQL SIMILAR TO pattern.
IncludeNamesarraynullList of routine names to include.
ExcludeNamesarraynullList of routine names to exclude.

Filtering Examples

Include only specific schemas:

json
json
{
  "NpgsqlRest": {
    "IncludeSchemas": ["api", "public"]
  }
}

Exclude internal schemas:

json
json
{
  "NpgsqlRest": {
    "ExcludeSchemas": ["pg_catalog", "information_schema", "internal"]
  }
}

Filter by name pattern:

json
json
{
  "NpgsqlRest": {
    "NameSimilarTo": "api_%",
    "NameNotSimilarTo": "%_internal"
  }
}

Comments Mode

SettingTypeDefaultDescription
CommentsModestring"OnlyWithHttpTag"How comment annotations affect endpoint creation.

Available modes:

ModeDescription
IgnoreCreate all endpoints, ignore comment annotations.
ParseAllCreate all endpoints, parse comment annotations to modify them.
OnlyWithHttpTagOnly create endpoints for routines with HTTP annotation in comments (default).

With the default OnlyWithHttpTag mode, routines without the HTTP annotation in their comment will not be exposed as endpoints. This provides explicit control over which database routines are accessible via the API.

URL and Naming

SettingTypeDefaultDescription
UrlPathPrefixstring"/api"URL prefix for all generated endpoints.
KebabCaseUrlsbooltrueConvert URL paths to kebab-case from PostgreSQL names.
CamelCaseNamesbooltrueConvert parameter names to camelCase from PostgreSQL names.

URL Examples

With default settings, get_user_profile becomes /api/get-user-profile.

json
json
{
  "NpgsqlRest": {
    "UrlPathPrefix": "/v1/api",
    "KebabCaseUrls": true
  }
}

Authorization

SettingTypeDefaultDescription
RequiresAuthorizationbooltrueForce all endpoints to require authorization. Can be overridden per endpoint via comment annotations.

Logging

SettingTypeDefaultDescription
LogConnectionNoticeEventsbooltrueLog PostgreSQL connection events (triggered by RAISE statements).
LogConnectionNoticeEventsModestring"FirstStackFrameAndMessage"How to format notice event logs.
LogCommandsboolfalseLog every executed command and query at debug level.
LogCommandParametersboolfalseInclude parameter values in command logs. Only applies when LogCommands is true.

Notice Event Modes

ModeDescription
MessageOnlyLog only the message.
FirstStackFrameAndMessageLog first stack frame and message (default).
FullStackAndMessageLog full stack trace and message.

HTTP Method and Parameters

SettingTypeDefaultDescription
DefaultHttpMethodstringnullForce HTTP method for all endpoints (GET, POST, PUT, DELETE, etc.).
DefaultRequestParamTypestringnullForce parameter location for all endpoints (QueryString or BodyJson).

Default Behavior

When DefaultHttpMethod is null:

  • GET is used when routine is not volatile, or name starts with get_, contains _get_, or ends with _get
  • POST is used otherwise

When DefaultRequestParamType is null:

  • QueryString for GET and DELETE endpoints
  • BodyJson for all other methods

Request Headers

SettingTypeDefaultDescription
RequestHeadersModestring"Parameter"How to send request headers to PostgreSQL routines.
RequestHeadersContextKeystring"request.headers"Context variable name when mode is Context.
RequestHeadersParameterNamestring"_headers"Parameter name when mode is Parameter.
CustomRequestHeadersobject{}Custom headers added to requests before sending to PostgreSQL.
InstanceIdRequestHeaderNamestringnullHeader name for NpgsqlRest instance ID. Set to null to disable.
ExecutionIdHeaderNamestring"X-NpgsqlRest-ID"Execution request header name. Used for request tracking and SSE correlation and in ConnectionSettings.UseJsonApplicationName.

Request Headers Modes

ModeDescription
IgnoreDon't send request headers to routines.
ContextSet context variable context.headers with JSON string via set_config().
ParameterSend headers to parameter named by RequestHeadersParameterName. Parameter must be JSON/text type with default value.

Connection Pooler Compatibility

New in 3.13.0

WrapInTransaction and BeforeRoutineCommands options for connection pooler compatibility and pre-routine SQL commands.

SettingTypeDefaultDescription
WrapInTransactionboolfalseWhen true, every request is wrapped in an explicit BEGIN ... COMMIT, and all set_config calls switch from session-scoped (is_local=false) to transaction-local (is_local=true).
BeforeRoutineCommandsarray[]SQL commands executed after any context is set but before the main routine call. Run in the same batch as the context set_config calls (no extra round-trip).

WrapInTransaction

This is required for connection poolers in transaction mode — including PgBouncer transaction-pool, AWS RDS Proxy in transaction mode, and Supabase Pooler. Previously, set_config(name, value, false) would set the GUC at the session level on the underlying PostgreSQL backend. With a transaction-mode pooler, the same backend is reused for unrelated client requests, which means session-scoped GUCs from one request could be visible to the next. With WrapInTransaction = true, GUCs are scoped to the request transaction and discarded on COMMIT.

The default remains false to preserve existing behavior; it is safe to leave off when using Npgsql's native pool only (which issues DISCARD ALL on connection return).

jsonc
jsonc
{
  "NpgsqlRest": {
    "WrapInTransaction": true
  }
}

BeforeRoutineCommands

Each entry can be either a raw SQL string (no parameters) or an object with Sql and Parameters. Each parameter has a Source (Claim, RequestHeader, or IpAddress) and an optional Name (claim type or header name). Parameter values are bound at request time from HttpContext — claim and header values are passed as parameterized SQL inputs (no string interpolation, no injection risk).

The most useful pattern is multi-tenant search_path setup driven by a JWT/cookie claim:

jsonc
jsonc
{
  "NpgsqlRest": {
    "WrapInTransaction": true,
    "BeforeRoutineCommands": [
      "select set_config('app.request_time', clock_timestamp()::text, true)",
      {
        "Sql": "select set_config('search_path', $1, true)",
        "Parameters": [{ "Source": "Claim", "Name": "tenant_id" }]
      }
    ]
  }
}

Per-request execution order with this config:

  1. BEGIN
  2. Each BeforeRoutineCommand is added as a NpgsqlBatchCommand (with parameters bound from claims/headers/IP) and dispatched in a single batch.
  3. The main routine call.
  4. COMMIT.

Steps 1–3 share a single network round-trip.

NULL Handling

SettingTypeDefaultDescription
QueryStringNullHandlingstring"Ignore"How empty or "null" query string values are interpreted.
TextResponseNullHandlingstring"EmptyString"How NULL database results are returned in plain text responses.

QueryStringNullHandling Values

ValueDescription
IgnoreNo special handling - empty strings stay as empty strings, "null" literal stays as "null" string (default).
EmptyStringEmpty query string values are interpreted as NULL values.
NullLiteralLiteral string "null" (case insensitive) is interpreted as NULL value.

TextResponseNullHandling Values

ValueDescription
EmptyStringReturns an empty string response with status code 200 OK (default).
NullLiteralReturns a string literal "NULL" with status code 200 OK.
NoContentReturns status code 204 NO CONTENT.

These settings can be overridden per-endpoint using comment annotations:

sql
sql
comment on function my_func(text) is '
@query_string_null_handling empty_string
@text_response_null_handling no_content
';

JSON Timestamp Handling

SettingTypeDefaultDescription
JsonTimestampsAreUtcbooltrueHow JSON-encoded timestamps are interpreted when parsed into timestamp, timestamptz, time, and timetz parameters.

When true (default, recommended):

  • Z-suffixed and offset-bearing ISO strings (e.g. "2026-05-20T06:00:00Z", "2026-05-20T08:00:00+02:00") are converted to UTC.
  • Naive ISO strings with no offset and no Z (e.g. "2026-05-20T06:00:00") are assumed UTC rather than interpreted as the host's local time.

The result is host-TZ-independent: the same JSON payload produces the same stored value regardless of the TZ environment of the process serving the request.

When false, the parsers fall back to the pre-3.16.0 behavior:

  • Z / offset-bearing strings are converted to the host's local time zone and tagged Kind=Local.
  • Naive strings are parsed as Kind=Unspecified.
  • The timestamptz / timetz parsers then re-apply SpecifyKind(Utc) on top of the local-shifted value — silently shifting the stored value by the host's UTC offset on non-UTC hosts.

Opt-out only — not recommended for new deployments

JsonTimestampsAreUtc: false exists as a compatibility escape hatch for callers that genuinely depend on the legacy "naive timestamps are host-local" behavior and cannot be updated to send Z-suffixed values. It reproduces the bug class fixed in 3.16.0. Leave at the default unless you have a specific legacy reason to flip it.

Example:

json
json
{
  "NpgsqlRest": {
    "JsonTimestampsAreUtc": true
  }
}

Server-Sent Events

Configure Server-Sent Events (SSE) for real-time streaming of PostgreSQL RAISE statements to connected clients.

SettingTypeDefaultDescription
DefaultServerSentEventsEventNoticeLevelstring"INFO"Default PostgreSQL notice level for SSE events. Valid values: INFO, NOTICE, WARNING.
ServerSentEventsResponseHeadersobject{}Custom headers added to SSE responses.

Notice Level Behavior

The DefaultServerSentEventsEventNoticeLevel setting determines which PostgreSQL RAISE statements generate SSE events by default when the level is not specified in the annotation.

Important

SSE events are sent only for the exact level configured, not for "this level and above". For example, if set to NOTICE, only RAISE NOTICE statements generate SSE events—RAISE INFO and RAISE WARNING are ignored.

This default can be overridden per-endpoint using the @sse annotation.

Example Configuration

json
json
{
  "NpgsqlRest": {
    "DefaultServerSentEventsEventNoticeLevel": "NOTICE",
    "ServerSentEventsResponseHeaders": {
      "X-Accel-Buffering": "no"
    }
  }
}

The X-Accel-Buffering: no header is commonly needed when running behind nginx to disable response buffering for SSE streams.

Complete Example

Production configuration:

json
json
{
  "NpgsqlRest": {
    "ConnectionName": null,
    "UseMultipleConnections": true,
    "CommandTimeout": "30 seconds",
    "IncludeSchemas": ["api"],
    "ExcludeSchemas": ["internal"],
    "CommentsMode": "OnlyWithHttpTag",
    "UrlPathPrefix": "/api",
    "KebabCaseUrls": true,
    "CamelCaseNames": true,
    "RequiresAuthorization": true,
    "LogConnectionNoticeEvents": true,
    "LogConnectionNoticeEventsMode": "FirstStackFrameAndMessage",
    "LogCommands": false,
    "LogCommandParameters": false,
    "RequestHeadersMode": "Parameter",
    "RequestHeadersParameterName": "_headers",
    "ExecutionIdHeaderName": "X-NpgsqlRest-ID"
  }
}

Development configuration with verbose logging:

json
json
{
  "NpgsqlRest": {
    "CommentsMode": "ParseAll",
    "RequiresAuthorization": false,
    "LogConnectionNoticeEvents": true,
    "LogConnectionNoticeEventsMode": "FullStackAndMessage",
    "LogCommands": true,
    "LogCommandParameters": true
  }
}

Next Steps

Comments