PostgreSQL wire protocol

PostgreSQL wire protocol


PostgreSQL wire protocol (он же «frontend/backend protocol» или «fe/be protocol») — это **очень большой, сложный и постоянно эволюционирующий** протокол.

Если коротко ответить на ваш вопрос:


**Полностью прикинуться PostgreSQL с нуля — это титанический труд, сопоставимый по объёму с написанием средней СУБД целиком.**

Большинство людей, которые хотят «подсунуть свою СУБД под инструменты PostgreSQL», идут совсем другим путём (об этом в конце).


### 1. Насколько он действительно большой?


Официальная документация: https://www.postgresql.org/docs/current/protocol.html

По состоянию на PostgreSQL 16 (2024–2025 гг.) протокол содержит:


#### Этапы соединения

- SSL negotiation

- GSSAPI / SCRAM-SHA-256 / MD5 / plaintext authentication (и плагины)

- StartupMessage → параметризация сессии (client_encoding, DateStyle, TimeZone и сотни других)

- ParameterStatus сообщения (их > 100 штук)


#### Основные типы сообщений

- Простой запрос (Simple Query) — всё ещё поддерживается, но почти никто серьёзный им не пользуется

- Расширенный запрос (Extended Query): Parse → Bind → Describe → Execute → Close

- CopyIn/CopyOut (включая CopyData + CopyDone + CopyFail)

- FunctionCall (вызов отдельной функции, используется pg_extension’ами)

- NotificationResponse (LISTEN/NOTIFY)

- SASL authentication exchange (SCRAM-SHA-256 — это 5–10 сообщений туда-сюда)


#### Форматы данных

- Текстовый и бинарный формат для каждого из ~200 встроенных типов (включая массивы, composite, range, jsonb, uuid, hstore, геометрию, pg_lsn и т.д.)

- OID’ы типов (да, до сих пор используются в протоколе)

- Поддержка пользовательских типов через typeinput/typeoutput функции (то есть драйверы ждут, что ты умеешь их читать/писать в бинарном виде)


#### Транзакции и расширенные фичи

- Sync/Flush

- Portal’ы (именованные результаты Execute)

- Prepare/EXECUTE (именованные prepared statements)

- Savepoints

- Two-phase commit (PREPARE TRANSACTION / COMMIT PREPARED)

- Replication protocol (логическая и физическая репликация — это вообще отдельный большой протокол, но он тоже идёт через тот же порт)


#### Совместимость с инструментами

Все современные драйверы и инструменты (libpq, pgjdbc, Npgsql, psycopg3, pgbouncer, pgpool, PostHog, Airbyte, почти все ORM и т.д.) используют **только Extended Query** и ожидают **полной поддержки SCRAM-SHA-256**, **бинарных форматов**, **ParameterStatus** и т.д.


### 2. Сколько это реально стоит реализовать?


Минимально рабочий подмодуль, с которым будут работать большинство современных клиентов (2025 год):


1. TLS + SCRAM-SHA-256(-PLUS)

2. Startup → ParameterStatus (минимум 15–20 параметров)

3. Extended Query цикл (Parse/Bind/Describe/Execute/Close)

4. Бинарные форматы хотя бы для 30–40 самых популярных типов (int2/4/8, float4/8, text, bytea, bool, timestamp/timestamptz, date, jsonb, uuid, numeric, arrays, numeric)

5. CommandComplete с правильными tag’ами (INSERT 0 5, SELECT 123 и т.д.)

6. ErrorResponse / NoticeResponse с полями (Severity, Code, Message, Detail, Hint и т.д.)

7. ReadyForQuery с правильным статусом транзакции (I/T/E)

8. CopyIn/CopyOut (многие ETL-инструменты требуют)


Это уже несколько тысяч строк очень аккуратного кода + постоянная гонка за новыми версиями PostgreSQL (каждые 9–12 месяцев добавляют новые типы и мелочи в протокол).


Реальные оценки людей, которые это делали:

- Yandex ClickHouse: ~2 человеко-года на «почти совместимый» postgresql interface (и до сих пор не 100%)

- Materialize: тоже около 2 лет на относительно полный протокол

- Neon serverless: писали свой postgres proxy → тоже огромные усилия

- TimescaleDB, Citus — просто форкнут PostgreSQL, потому что иначе не получается


### 3. Реальные альтернативы (что делают все умные люди)


99% проектов, которые хотят «использовать экосистему PostgreSQL, но иметь свою СУБД», выбирают один из вариантов:


#### Вариант A (самый популярный): Postgres proxy / adapter

Запускаете настоящий PostgreSQL (можно даже без данных — empty database), а внутри пишете extension на C/Rust (через PGX или SPI), которая перенаправляет все запросы в вашу СУБД.

Примеры:

- FerretDB (MongoDB wire → PostgreSQL)

- EdgeDB (свой язык → PostgreSQL backend)

- Hydra (Columnar → PostgreSQL protocol)


Плюсы: 100% совместимость, всё работает из коробки.

Минусы: нужен настоящий PostgreSQL рядом.


#### Вариант B: pgwire библиотеки

Вместо писать протокол с нуля — берёте готовую реализацию:


- Rust: postgres-wire (от Supabase), pgwire (от RisingWave), bb8-postgres-compat

- Go: pgx/pgproto, jackc/pgproto

- Java: уже есть в pgjdbc, но можно использовать как библиотеку


Эти библиотеки реализуют 80–90% протокола. Осталось «только» реализовать обработку запросов и форматы данных.


#### Вариант C: «облегчённый» PostgreSQL протокол

Поддерживаете только Simple Query + текстовый формат + MD5 auth.

Работает с: psql, старыми драйверами, pg_dump (частично).

Не работает с: ORMs, connection poolers (pgbouncer в transaction pooling), большинством современных инструментов.


### 4. Вывод для вашего случая


Если у вас маленькая самописная СУБД и примитивный протокол с 15 командами, то:


Полная эмуляция PostgreSQL = переписать половину PostgreSQL. Не делайте так.


Рекомендуемые пути по убыванию трудозатрат:


1. Самый быстрый: запустите лёгкий PostgreSQL + свою extension на Rust/C → 100% совместимость за недели.

2. Средний: возьмите pgwire (Rust) или pgproto (Go) и реализуйте свой бэкенд → несколько месяцев работы одного человека на «достаточно совместимый» уровень.

3. Долгий и болезненный: пишете протокол полностью сами → годы поддержки.


Большинство успешных «PostgreSQL-совместимых» проектов последних лет (Neon, Supabase storage, RisingWave, Hydra, etc.) выбрали варианты 1 или 2.


Так что ответ на ваш вопрос «что мне будет стоить прикинуться PostgreSQL» — это либо «очень дорого», либо «недорого, но через настоящий PostgreSQL или готовую pgwire-библиотеку». Полностью с нуля — почти никогда не оправдано.

Report Page