PostgreSQL
PostgreSQL на 1M+ QPS: опыт компаний
Instagram, Stripe, Notion обрабатывают сотни миллионов операций в день на PostgreSQL. Как они это делают - и почему не перешли на NoSQL?
- Stripe обработал $817 млрд платежей в 2022 году на PostgreSQL с pgbouncer и partitioning
- Instagram шардировал PostgreSQL на 1200+ инстансов без замены на NoSQL, встроив shard_id в 64-bit ID
- Notion шардировал монолитный PostgreSQL за 6 месяцев без единого downtime-инцидента
Instagram: PostgreSQL на 1 млрд пользователей
Instagram запустился на PostgreSQL в 2010 году и к 2012 году обслуживал 30 млн пользователей с одним сервером. Ключевое архитектурное решение: горизонтальное шардирование по user_id до того, как вертикальное масштабирование исчерпало ресурс.
Instagram выбрал PostgreSQL из-за богатой системы типов (arrays, hstore до появления jsonb), надёжных транзакций и активного сообщества. К 2013 году: 1200+ шардов, каждый - полноценный PostgreSQL-инстанс с репликой. Автоматическое шардирование реализовано на уровне Python-ORM.
Проблема UUID vs bigint: Instagram перешёл с UUID на 64-bit ID (Instagram ID), встраивая в ID временную метку и номер шарда. Это позволило декодировать шард без обращения к routing-таблице и сортировать записи по времени создания без отдельного поля created_at.
К 2022 году Meta (Instagram) мигрировала часть нагрузки на MySQL для унификации инфраструктуры, но PostgreSQL остался на критических системах. Опыт Instagram стал основой для open-source шардинг-библиотек в экосистеме Python.
Почему Instagram встроил shard_id в 64-bit ID записей?
Notion: от монолита к шардированию за 6 месяцев
В 2021 году Notion столкнулся с деградацией производительности: один PostgreSQL-кластер с 100+ млн страниц, p99 latency рос, autovacuum не справлялся с объёмом bloat. Команда приняла решение о шардировании за 6 месяцев.
Notion выбрал шардирование по block_id (основная сущность в Notion - block). Ключевой принцип: все операции над workspace выполняются в пределах одного шарда - это обеспечивает атомарность без distributed transactions.
Технические детали миграции: Notion использовал postgres_fdw для временного доступа к данным старого монолита в период backfill. Double-write обеспечивал консистентность. Весь процесс занял 6 месяцев, без единого downtime-инцидента по причине шардирования.
Notion опубликовал post-mortem о шардировании в своём блоге. Ключевой вывод: шардировать надо ДО того, как начались проблемы с производительностью - оставлять запас минимум 2x по текущей нагрузке.
После шардирования: autovacuum работает эффективно на меньших таблицах, query plans стабильны, p99 latency снизилась на 40%. Дополнительный эффект: hot шарды видны в мониторинге, проще изолировать проблемных клиентов.
Почему Notion шардировал по block_id, а не по user_id?
Supabase: PostgreSQL как платформа
Supabase предоставляет PostgreSQL как managed service с расширенными возможностями: Row Level Security для multi-tenancy, реалтайм через logical replication, REST API через PostgREST, GraphQL через pg_graphql. Каждый проект - отдельный PostgreSQL-инстанс.
Реалтайм в Supabase построен на logical replication: отдельный сервис (написан на Elixir) подключается к PostgreSQL как logical replication slot, парсит WAL и отправляет изменения клиентам через WebSocket. Это позволяет подписываться на изменения таблиц в реальном времени без polling.
Supabase запустил pgvector как первоклассную функцию: у каждого проекта расширение pgvector активировано по умолчанию. Это привело к взрывному росту adoption - в 2023 году Supabase стал крупнейшей managed-платформой для PostgreSQL с pgvector, опередив AWS RDS по количеству векторных индексов.
К 2024 году Supabase обслуживает 1M+ PostgreSQL инстансов. Инфраструктура: Fly.io для compute, каждый инстанс - изолированный контейнер. Хранилище данных: S3-совместимое через Supabase Storage с FDW.
Как Supabase реализует реалтайм-подписки на изменения таблиц?
Стратегии шардирования PostgreSQL
Шардирование PostgreSQL реализуется на нескольких уровнях: application-level (самый распространённый), middleware (Citus, pg_partman для partitioning), или через FDW. Каждый подход имеет свои trade-offs по сложности, производительности и поддерживаемости.
Declarative partitioning (PG 10+) - нативный инструмент PostgreSQL для вертикального масштабирования без application-level шардирования. Range partitioning по дате для time-series, hash partitioning для равномерного распределения. Partition pruning позволяет планировщику игнорировать нерелевантные партиции.
Шардирование усложняет JOIN, транзакции, UNIQUE constraints и sequence. Перед шардированием нужно исчерпать: индексы, partitioning, connection pooling, read replicas, caching. Шардирование - последний рубеж, не первый.
Что такое partition pruning в PostgreSQL?
Практические уроки масштабирования
Компании, масштабировавшие PostgreSQL до 1M+ QPS, выработали общие принципы. Они расходятся с интуицией начинающих и подкреплены production-данными из реальных post-mortem и engineering blog-постов.
Stripe обработал $817 млрд платежей в 2022 году на PostgreSQL-кластерах. Ключевые решения: aggressive connection pooling через Pgbouncer, separate read clusters для аналитики, partitioning charges/payment_intents по customer_id. Stripe никогда не переходил на NoSQL для core payments - PostgreSQL с правильной настройкой справляется с любой нагрузкой финтеха.
GitLab мигрировал с MySQL на PostgreSQL в 2018 году и сразу получил 40% снижение нагрузки на базу за счёт лучшего планировщика запросов. Использует Patroni + Consul для HA, 3 read replica, pgbouncer. Весь GitLab.com работает на одном нешардированном PostgreSQL-кластере с правильной настройкой autovacuum и партиционированием по namespace_id.
PostgreSQL не масштабируется для высоких нагрузок - нужен NoSQL
PostgreSQL масштабируется до 1M+ QPS при правильной настройке. Instagram, Stripe, GitLab, Notion - все работают на PostgreSQL при огромных нагрузках.
Узкие места PostgreSQL - connection overhead (решается pgbouncer), bloat (решается autovacuum tuning), и отсутствие horizontal scaling (решается read replicas + partitioning + Citus). NoSQL жертвует ACID и богатой системой запросов, не давая чудес при правильно настроенном PostgreSQL.
Какой подход Stripe использует для масштабирования core payments?
PostgreSQL на масштабе
- Instagram: шардирование по user_id, 64-bit ID с embedded shard_id, 1200+ PostgreSQL инстансов
- Notion: шардирование по block_id за 6 месяцев без downtime, dual-write + backfill + switchover
- Supabase: logical replication WAL → Elixir → WebSocket как основа реалтайма, pgvector по умолчанию
- Partitioning + connection pooling + read replicas покрывают 95% нагрузок без шардирования
- Шардировать нужно поздно - Stripe и GitLab работают на нешардированном PostgreSQL при огромных нагрузках
Связанные темы
Масштабирование PostgreSQL требует понимания всего стека
- Citus — Citus - managed решение для горизонтального шардирования без application-level routing
- Connection Pooling — PgBouncer - первый шаг масштабирования, обязателен до шардирования
- Логическая репликация — Logical replication - основа Supabase Realtime и zero-downtime миграций
Вопросы для размышления
- При каком объёме данных или нагрузке стоит задуматься о шардировании вместо дальнейшей оптимизации одного кластера?
- Почему Stripe и GitLab могут работать на нешардированном PostgreSQL, а Instagram и Notion перешли к шардированию?
- Какие компромиссы принимает Supabase, используя logical replication для реалтайма вместо triggers?