Skip to content
Effect Days 2026 Early bird tickets

PgProtocol

Wire codec for the PostgreSQL frontend/backend protocol, version 3.0.

The module encodes frontend messages and decodes backend messages. Every function is pure: bytes in, bytes or plain data out. Nothing here opens a socket, negotiates TLS, or tracks session state, and nothing here decodes column values - DataRow fields stay raw bytes for PgTypes to interpret.

Typed messages are a type byte, an int32 length that counts itself but not the type byte, and a payload. Integers are big-endian and strings are NUL-terminated UTF-8 unless they are explicitly length-prefixed.

Encoded frames and decoded byte fields are views into pooled buffers that are written once and never rewritten. They stay valid for as long as they are held, but holding one keeps its whole pool buffer alive, so copy anything that has to outlive the message it came from.

72 exports Added in v4.0.0 Source

Constants

Default maxMessageSize for makeParser: 16 MiB.

Signature

declare const defaultMaxMessageSize: number

Constructors

makeParser

Added in v4.0.0 Source

Creates a Parser.

Special pre-startup replies have no type byte and are not handled here; use decodeSslResponse for those.

Signature

declare function makeParser<A = Uint8Array<ArrayBufferLike> | null>(options?: {
readonly maxMessageSize?: number;
readonly readField?: FieldReader<A>;
}): Parser<A>

Decoding

Decodes the single byte the server sends in reply to an SSLRequest. "S" means the server will speak TLS, "N" means it will not.

Signature

declare function decodeSslResponse(byte: number): Result<"S" | "N", ParseError>

Encoding

encode

Added in v4.0.0 Source

Encodes any frontend message.

Signature

declare function encode(message: FrontendMessage): Result<Uint8Array<ArrayBufferLike>, EncodeError>

Encodes a CancelRequest. It has no type byte and is sent on a separate connection, using the pid and secret from BackendKeyData.

Signature

declare function encodeCancelRequest(options: {
readonly pid: number;
readonly secret: number;
}): Uint8Array

encodeClose

Added in v4.0.0 Source

Encodes a Close message.

Signature

declare function encodeClose(options: Omit<Close, "_tag">): Uint8Array

Encodes a Describe message.

Signature

declare function encodeDescribe(options: Omit<Describe, "_tag">): Uint8Array

Encodes an Execute message.

Signature

declare function encodeExecute(options: Omit<Execute, "_tag">): Uint8Array

encodeFlush

Added in v4.0.0 Source

Encodes a Flush message.

Signature

declare function encodeFlush(): Uint8Array

Encodes a PasswordMessage. The password is sent verbatim, so MD5 hashing belongs to the caller - see PgAuth.md5Password.

Signature

declare function encodePasswordMessage(options: Omit<PasswordMessage, "_tag">): Uint8Array

Encodes a SASLInitialResponse message.

Signature

declare function encodeSASLInitialResponse(options: Omit<SASLInitialResponse, "_tag">): Uint8Array

Encodes a SASLResponse message.

Signature

declare function encodeSASLResponse(options: Omit<SASLResponse, "_tag">): Uint8Array

Encodes an SSLRequest. It has no type byte and is only valid before startup.

Signature

declare function encodeSslRequest(): Uint8Array

Encodes a StartupMessage for protocol 3.0. It has no type byte. client_encoding defaults to UTF8 because this codec always writes UTF-8.

Signature

declare function encodeStartupMessage(parameters: StartupParameters): Uint8Array

encodeSync

Added in v4.0.0 Source

Encodes a Sync message.

Signature

declare function encodeSync(): Uint8Array

Encodes a Terminate message.

Signature

declare function encodeTerminate(): Uint8Array

Errors

EncodeError

Added in v4.0.0 Source

Error returned when a frontend message cannot be encoded.

Signature

declare class EncodeError extends any {
constructor();
}

ParseError

Added in v4.0.0 Source

Error produced when bytes cannot be interpreted as a protocol message.

Signature

declare class ParseError extends any {
constructor();
}

Models

The server wants the password in the clear.

Signature

interface AuthenticationCleartextPassword {
readonly _tag: "AuthenticationCleartextPassword";
}

AuthenticationMD5Password interface

Added in v4.0.0 Source

The server wants an MD5-hashed password, salted with these four bytes.

Signature

interface AuthenticationMD5Password {
readonly _tag: "AuthenticationMD5Password";
readonly salt: Uint8Array;
}

AuthenticationOk interface

Added in v4.0.0 Source

Authentication succeeded.

Signature

interface AuthenticationOk {
readonly _tag: "AuthenticationOk";
}

AuthenticationSASL interface

Added in v4.0.0 Source

The server offers these SASL mechanisms.

Signature

interface AuthenticationSASL {
readonly _tag: "AuthenticationSASL";
readonly mechanisms: readonly Array<string>;
}

AuthenticationSASLContinue interface

Added in v4.0.0 Source

An opaque SASL challenge.

Signature

interface AuthenticationSASLContinue {
readonly _tag: "AuthenticationSASLContinue";
readonly data: Uint8Array;
}

AuthenticationSASLFinal interface

Added in v4.0.0 Source

The opaque final SASL payload, carrying the server signature.

Signature

interface AuthenticationSASLFinal {
readonly _tag: "AuthenticationSASLFinal";
readonly data: Uint8Array;
}

AuthenticationUnsupported interface

Added in v4.0.0 Source

An authentication request this codec does not model, such as GSSAPI or SSPI. The method is the raw sub-type integer.

Signature

interface AuthenticationUnsupported {
readonly _tag: "AuthenticationUnsupported";
readonly method: number;
readonly payload: Uint8Array;
}

BackendKeyData interface

Added in v4.0.0 Source

The identity a CancelRequest needs.

Signature

interface BackendKeyData {
readonly _tag: "BackendKeyData";
readonly pid: number;
readonly secret: number;
}

BackendMessage type

Added in v4.0.0 Source

Any message the server sends after startup.

Signature

type BackendMessage<A = Uint8Array | null> = AuthenticationOk | AuthenticationCleartextPassword | AuthenticationMD5Password | AuthenticationSASL | AuthenticationSASLContinue | AuthenticationSASLFinal | AuthenticationUnsupported | ParameterStatus | BackendKeyData | ReadyForQuery | RowDescription | DataRow<A> | CommandComplete | EmptyQueryResponse | NoData | ParseComplete | BindComplete | CloseComplete | PortalSuspended | ParameterDescription | ErrorResponse | NoticeResponse | NotificationResponse | NegotiateProtocolVersion | CopyInResponse | CopyOutResponse | CopyBothResponse | CopyData | CopyDone | Unknown

Bind interface

Added in v4.0.0 Source

Binds parameter values to a prepared statement, creating a portal.

Parameters and results always use the binary format code.

Signature

interface Bind {
readonly _tag: "Bind";
readonly parameters: readonly Array<Uint8Array<ArrayBufferLike> | null>;
readonly portal: string;
readonly statement: string;
}

BindComplete interface

Added in v4.0.0 Source

A Bind succeeded.

Signature

interface BindComplete {
readonly _tag: "BindComplete";
}

Close interface

Added in v4.0.0 Source

Drops a prepared statement or portal.

Signature

interface Close {
readonly _tag: "Close";
readonly name: string;
readonly target: DescribeTarget;
}

CloseComplete interface

Added in v4.0.0 Source

A Close succeeded.

Signature

interface CloseComplete {
readonly _tag: "CloseComplete";
}

CommandComplete interface

Added in v4.0.0 Source

A command finished, reporting its tag such as SELECT 3.

Signature

interface CommandComplete {
readonly _tag: "CommandComplete";
readonly commandTag: string;
}

CopyBothResponse interface

Added in v4.0.0 Source

The connection entered bidirectional COPY mode, as used by replication.

Signature

interface CopyBothResponse {
readonly _tag: "CopyBothResponse";
readonly columnFormats: readonly Array<number>;
readonly format: number;
}

CopyData interface

Added in v4.0.0 Source

A chunk of COPY data.

Signature

interface CopyData {
readonly _tag: "CopyData";
readonly data: Uint8Array;
}

CopyDone interface

Added in v4.0.0 Source

The COPY stream ended.

Signature

interface CopyDone {
readonly _tag: "CopyDone";
}

CopyInResponse interface

Added in v4.0.0 Source

The server is ready to receive COPY data.

Signature

interface CopyInResponse {
readonly _tag: "CopyInResponse";
readonly columnFormats: readonly Array<number>;
readonly format: number;
}

CopyOutResponse interface

Added in v4.0.0 Source

The server is about to send COPY data.

Signature

interface CopyOutResponse {
readonly _tag: "CopyOutResponse";
readonly columnFormats: readonly Array<number>;
readonly format: number;
}

DataRow interface

Added in v4.0.0 Source

One result row. Values stay raw bytes; null is SQL NULL. Decoding them requires the OIDs from the matching RowDescription.

Signature

interface DataRow<out A = Uint8Array | null> {
readonly _tag: "DataRow";
readonly values: readonly Array<A>;
}

Describe interface

Added in v4.0.0 Source

Asks for the parameter and row shape of a statement or portal.

Signature

interface Describe {
readonly _tag: "Describe";
readonly name: string;
readonly target: DescribeTarget;
}

DescribeTarget type

Added in v4.0.0 Source

Which kind of object a Describe or Close message names.

Signature

type DescribeTarget = "statement" | "portal"

EmptyQueryResponse interface

Added in v4.0.0 Source

The query string was empty.

Signature

interface EmptyQueryResponse {
readonly _tag: "EmptyQueryResponse";
}

ErrorFields interface

Added in v4.0.0 Source

The fields of an ErrorResponse or NoticeResponse. Unrecognised field codes are kept under their raw single-character key.

Signature

interface ErrorFields {
[key: string]: string | undefined;
readonly code?: string;
readonly column?: string;
readonly constraint?: string;
readonly dataType?: string;
readonly detail?: string;
readonly file?: string;
readonly hint?: string;
readonly internalPosition?: string;
readonly internalQuery?: string;
readonly line?: string;
readonly message?: string;
readonly position?: string;
readonly routine?: string;
readonly schema?: string;
readonly severity?: string;
readonly severityUnlocalized?: string;
readonly table?: string;
readonly where?: string;
}

ErrorResponse interface

Added in v4.0.0 Source

An error. code is the SQLSTATE.

Signature

interface ErrorResponse {
readonly _tag: "ErrorResponse";
readonly fields: ErrorFields;
}

Execute interface

Added in v4.0.0 Source

Runs a portal, optionally limiting the number of rows returned.

Signature

interface Execute {
readonly _tag: "Execute";
readonly maxRows: number;
readonly portal: string;
}

FieldDescription interface

Added in v4.0.0 Source

One column of a RowDescription.

Signature

interface FieldDescription {
readonly columnAttributeNumber: number;
readonly dataTypeOid: number;
readonly dataTypeSize: number;
readonly format: number;
readonly name: string;
readonly tableOid: number;
readonly typeModifier: number;
}

FieldReader type

Added in v4.0.0 Source

Reads one DataRow field out of the parser's buffer, for a parser given a readField. size is -1 for SQL NULL, and column is the field's position in the row.

The bytes are the parser's buffer rather than a view of the field, so they are only the field's for offset to offset + size, and reading outside that reads the rest of the stream. PgTypes.makeFieldReader is the implementation for OID-typed columns.

A reader runs inside the stateful parser. If it throws, that failure is terminal just like a ParseError.

Signature

type FieldReader<A> = (bytes: Uint8Array, offset: number, size: number, column: number) => A

Flush interface

Added in v4.0.0 Source

Asks the backend to deliver buffered output without ending the transaction.

Signature

interface Flush {
readonly _tag: "Flush";
}

FrontendMessage type

Added in v4.0.0 Source

Any message the client sends after startup.

Signature

type FrontendMessage = Parse | Bind | Execute | Describe | Close | Sync | Flush | Terminate | PasswordMessage | SASLInitialResponse | SASLResponse

NegotiateProtocolVersion interface

Added in v4.0.0 Source

The server speaks an older minor protocol version, or did not recognise some startup options.

Signature

interface NegotiateProtocolVersion {
readonly _tag: "NegotiateProtocolVersion";
readonly minorVersion: number;
readonly unrecognizedOptions: readonly Array<string>;
}

NoData interface

Added in v4.0.0 Source

The statement or portal returns no rows.

Signature

interface NoData {
readonly _tag: "NoData";
}

NoticeResponse interface

Added in v4.0.0 Source

A warning or notice. Same field set as ErrorResponse.

Signature

interface NoticeResponse {
readonly _tag: "NoticeResponse";
readonly fields: ErrorFields;
}

NotificationResponse interface

Added in v4.0.0 Source

A LISTEN/NOTIFY message.

Signature

interface NotificationResponse {
readonly _tag: "NotificationResponse";
readonly channel: string;
readonly payload: string;
readonly pid: number;
}

ParameterDescription interface

Added in v4.0.0 Source

The parameter OIDs of a described statement.

Signature

interface ParameterDescription {
readonly _tag: "ParameterDescription";
readonly parameterTypes: readonly Array<number>;
}

ParameterStatus interface

Added in v4.0.0 Source

Reports a run-time parameter value, at startup or whenever it changes.

Signature

interface ParameterStatus {
readonly _tag: "ParameterStatus";
readonly name: string;
readonly value: string;
}

Parse interface

Added in v4.0.0 Source

Prepares a named or unnamed statement.

Signature

interface Parse {
readonly _tag: "Parse";
readonly name: string;
readonly parameterTypes: readonly Array<number>;
readonly query: string;
}

ParseComplete interface

Added in v4.0.0 Source

A Parse succeeded.

Signature

interface ParseComplete {
readonly _tag: "ParseComplete";
}

Parser interface

Added in v4.0.0 Source

An incremental decoder for the post-startup backend message stream.

Signature

interface Parser<A = Uint8Array | null> {
readonly push: (chunk: Uint8Array) => readonly Array<BackendMessage<A>>;
readField: FieldReader<A> | undefined;
}

PasswordMessage interface

Added in v4.0.0 Source

Answers a cleartext or MD5 password request.

Signature

interface PasswordMessage {
readonly _tag: "PasswordMessage";
readonly password: string;
}

PortalSuspended interface

Added in v4.0.0 Source

An Execute stopped at its row limit; the portal can be executed again.

Signature

interface PortalSuspended {
readonly _tag: "PortalSuspended";
}

ReadyForQuery interface

Added in v4.0.0 Source

The backend is ready for a new query cycle.

Signature

interface ReadyForQuery {
readonly _tag: "ReadyForQuery";
readonly status: TransactionStatus;
}

RowDescription interface

Added in v4.0.0 Source

Describes the columns a portal will return.

Signature

interface RowDescription {
readonly _tag: "RowDescription";
readonly fields: readonly Array<FieldDescription>;
}

SASLInitialResponse interface

Added in v4.0.0 Source

Selects a SASL mechanism and carries its opaque initial response.

Signature

interface SASLInitialResponse {
readonly _tag: "SASLInitialResponse";
readonly initialResponse: Uint8Array<ArrayBufferLike> | null;
readonly mechanism: string;
}

SASLResponse interface

Added in v4.0.0 Source

Carries an opaque SASL continuation payload.

Signature

interface SASLResponse {
readonly _tag: "SASLResponse";
readonly data: Uint8Array;
}

StartupParameters interface

Added in v4.0.0 Source

Startup parameters. user is required; any other run-time parameter the server accepts may be passed alongside it.

Signature

interface StartupParameters {
[key: string]: string | undefined;
readonly application_name?: string;
readonly database?: string;
readonly user: string;
}

Sync interface

Added in v4.0.0 Source

Closes the current transaction block and requests a ReadyForQuery.

Signature

interface Sync {
readonly _tag: "Sync";
}

Terminate interface

Added in v4.0.0 Source

Ends the session.

Signature

interface Terminate {
readonly _tag: "Terminate";
}

TransactionStatus type

Added in v4.0.0 Source

Transaction status: idle, in a transaction block, or in a failed transaction block.

Signature

type TransactionStatus = "I" | "T" | "E"

Unknown interface

Added in v4.0.0 Source

A message whose type byte this codec does not know. The payload excludes the type byte and the length prefix.

Signature

interface Unknown {
readonly _tag: "Unknown";
readonly payload: Uint8Array;
readonly type: number;
}

ValueSink interface

Added in v4.0.0 Source

Where a value writes its wire bytes. Bind frames a parameter by leaving room for its length, letting the sink fill in the body, and backfilling the length from what was written, so a value never needs an array of its own.

PgTypes.writeParameter is the implementation for OID-typed values.

Signature

interface ValueSink {
readonly beginLength: () => number;
readonly bigInt64: (value: bigint) => void;
readonly endLength: (token: number) => void;
readonly float32: (value: number) => void;
readonly float64: (value: number) => void;
readonly int16: (value: number) => void;
readonly int32: (value: number) => void;
readonly raw: (value: Uint8Array) => void;
readonly sqlNull: () => void;
readonly uint8: (value: number) => void;
readonly utf8: (value: string) => void;
}

Other

Signature

declare function encodeBind(options: Omit<Bind, "_tag">): Result<Uint8Array<ArrayBufferLike>, EncodeError>

Signature

declare function encodeParse(options: Omit<Parse, "_tag">): Result<Uint8Array<ArrayBufferLike>, EncodeError>

Signature

declare function makeBindEncoder<A, E = never>(writeParameter: (sink: ValueSink, value: A) => Result<void, E>): (options: {
readonly parameters: readonly Array<A>;
readonly portal: string;
readonly statement: string;
}) => Result<Uint8Array<ArrayBufferLike>, EncodeError | E>