The protocol has separate phases for startup and normal
operation. In the startup phase, the frontend opens a connection to
the server and authenticates itself to the satisfaction of the
server. (This might involve a single message, or multiple messages
depending on the authentication method being used.) If all goes
well, the server then sends status information to the frontend, and
finally enters normal operation. Except for the initial
startup-request message, this part of the protocol is driven by the
server.

During normal operation, the frontend sends queries and other
commands to the backend, and the backend sends back query results
and other responses. There are a few cases (such as NOTIFY) wherein the backend will send unsolicited
messages, but for the most part this portion of a session is driven
by frontend requests.

Termination of the session is normally by frontend choice, but
can be forced by the backend in certain cases. In any case, when
the backend closes the connection, it will roll back any open
(incomplete) transaction before exiting.

Within normal operation, SQL commands can be executed through
either of two sub-protocols. In the "simple
query" protocol, the frontend just sends a textual query
string, which is parsed and immediately executed by the backend. In
the "extended query" protocol,
processing of queries is separated into multiple steps: parsing,
binding of parameter values, and execution. This offers flexibility
and performance benefits, at the cost of extra complexity.

Normal operation has additional sub-protocols for special
operations such as COPY.

All communication is through a stream of messages. The first
byte of a message identifies the message type, and the next four
bytes specify the length of the rest of the message (this length
count includes itself, but not the message-type byte). The
remaining contents of the message are determined by the message
type. For historical reasons, the very first message sent by the
client (the startup message) has no initial message-type byte.

To avoid losing synchronization with the message stream, both
servers and clients typically read an entire message into a buffer
(using the byte count) before attempting to process its contents.
This allows easy recovery if an error is detected while processing
the contents. In extreme situations (such as not having enough
memory to buffer the message), the receiver can use the byte count
to determine how much input to skip before it resumes reading
messages.

Conversely, both servers and clients must take care never to
send an incomplete message. This is commonly done by marshaling the
entire message in a buffer before beginning to send it. If a
communications failure occurs partway through sending or receiving
a message, the only sensible response is to abandon the connection,
since there is little hope of recovering message-boundary
synchronization.

In the extended-query protocol, execution of SQL commands is
divided into multiple steps. The state retained between steps is
represented by two types of objects: prepared
statements and portals. A prepared
statement represents the result of parsing and semantic analysis of
a textual query string. A prepared statement is not in itself ready
to execute, because it might lack specific values for parameters. A portal represents a ready-to-execute
or already-partially-executed statement, with any missing parameter
values filled in. (For SELECT statements,
a portal is equivalent to an open cursor, but we choose to use a
different term since cursors don't handle non-SELECT statements.)

The overall execution cycle consists of a parse step, which creates a prepared statement from
a textual query string; a bind step, which
creates a portal given a prepared statement and values for any
needed parameters; and an execute step
that runs a portal's query. In the case of a query that returns
rows (SELECT, SHOW, etc), the execute step can be told to fetch
only a limited number of rows, so that multiple execute steps might
be needed to complete the operation.

The backend can keep track of multiple prepared statements and
portals (but note that these exist only within a session, and are
never shared across sessions). Existing prepared statements and
portals are referenced by names assigned when they were created. In
addition, an "unnamed" prepared
statement and portal exist. Although these behave largely the same
as named objects, operations on them are optimized for the case of
executing a query only once and then discarding it, whereas
operations on named objects are optimized on the expectation of
multiple uses.

Data of a particular data type might be transmitted in any of
several different formats. As of
PostgreSQL 7.4 the only supported
formats are "text" and "binary", but the protocol makes provision for
future extensions. The desired format for any value is specified by
a format code. Clients can specify a
format code for each transmitted parameter value and for each
column of a query result. Text has format code zero, binary has
format code one, and all other format codes are reserved for future
definition.

The text representation of values is whatever strings are
produced and accepted by the input/output conversion functions for
the particular data type. In the transmitted representation, there
is no trailing null character; the frontend must add one to
received values if it wants to process them as C strings. (The text
format does not allow embedded nulls, by the way.)

Binary representations for integers use network byte order (most
significant byte first). For other data types consult the
documentation or source code to learn about the binary
representation. Keep in mind that binary representations for
complex data types might change across server versions; the text
format is usually the more portable choice.

Submit correction

If you see anything in the documentation that is not correct, does not match
your experience with the particular feature or requires further clarification,
please use
this form
to report a documentation issue.