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-библиотеку». Полностью с нуля — почти никогда не оправдано.