PACELC Theorem concept page — расширение CAP, добавляющее Latency vs Consistency trade-off в нормальной работе. 4 multi-scenario анимации показывают одну топологию (coordinator + 3 replicas в разных регионах + client) в режимах PA/EL (Cassandra ONE/ONE), PA/EC (tunable QUORUM), PC/EC (MongoDB default при partition), PC/EC (Spanner с TrueTime). Включает ADR с pedagogical context на coordinator-ноде.
CAP-теорема популярна, но в production-системах она описывает редкое событие. Network partition — это не штатный режим работы. В нормальном дата-центре сеть стабильна часами и сутками: partition случается раз в месяц-квартал, занимает минуты, и обычно затрагивает узкий сегмент. Между тем база данных принимает миллионы запросов в секунду — и каждый из них тоже сталкивается с trade-off, который CAP не описывает: latency vs consistency.
PACELC (Daniel Abadi, 2010) закрывает эту дыру. Когда инженер выбирает Cassandra, DynamoDB, Spanner или MongoDB, он на самом деле принимает два решения: как система ведёт себя при partition (это CAP) и как она ведёт себя при нормальной работе (это PACELC ELSE). Без второй части нельзя осмысленно сравнивать «AP-системы» между собой — Cassandra с consistency=ONE и Cassandra с consistency=QUORUM это два разных продукта по latency. Курс на архитектора без PACELC оставляет слепую зону шириной в 99% времени работы системы.
Одна формула, две ветки:
If Partition — Availability or Consistency. Else — Latency or Consistency.
Сильная консистентность всегда стоит latency. Чтобы гарантировать, что клиент прочитает свой собственный write, нужно дождаться подтверждения от кворума реплик. Кворум через дата-центры — это +30-100ms. Кворум через регионы — +80-200ms. Если ты согласен на eventual consistency и читаешь из ближайшей реплики, latency = единицы миллисекунд. Это и есть ELSE-часть PACELC: каждая sync-replica — это налог на latency, каждая async-replica — окно для stale read.
Любую систему можно отнести к одному из четырёх классов: PA/EL, PA/EC, PC/EL, PC/EC. Реальный выбор почти всегда сводится к двум — PA/EL (Cassandra, DynamoDB, Riak) или PC/EC (Spanner, etcd, MongoDB default). PA/EC и PC/EL — редкие и чаще всего возникают как побочный эффект tunable конфигов.
На канвасе одна топология — distributed database из четырёх компонентов: Coordinator (router-роль) и три Replica в географически разнесённых локациях (us-east, us-west, eu-west). Слева отдельно — клиент. Edges от координатора к репликам подписаны характерным latency: 1ms до LAN-реплики, 30ms до cross-DC, 80ms до cross-region. Эти числа задают шкалу: всё, что мы видим в анимациях, — производное от этой геометрии.
На coordinator-ноде висит ADR-001 «PACELC: расширение CAP» — это формальная запись того, почему мы вообще говорим про две буквы вместо одной. Откройте её через клик на узле, чтобы прочитать context, decision и год публикации Абади.
Топология специально оставлена одна на все сценарии: смысл PACELC именно в том, что одна и та же физическая система может вести себя как PA/EL или PC/EC в зависимости от настроек consistency-level и от того, есть ли сейчас partition. Меняем не железо — меняем поведение.
pa-el-cassandra — Cassandra ONE/ONE (fast eventual). Самый дешёвый режим: пишем в одну реплику, читаем из одной. Write возвращается за ~3ms, read возвращается за единицы миллисекунд. Но во второй части сценария мы читаем с реплики, которая ещё не получила update — и видим stale value. Урок: в PA/EL latency минимальна, но клиент должен быть готов к временно устаревшим данным. Для timeline-ов и feed-ов это норма.
pa-ec-quorum — tunable QUORUM (W=2, R=2, N=3). Та же Cassandra, но с другим уровнем consistency. Write ждёт подтверждения от 2 реплик из 3 (~30ms — медианная latency cross-DC). Read забирает значение из 2 реплик и выбирает свежее по timestamp. Формула W + R > N гарантирует strong consistency. Урок: tunable consistency — это рычаг per-query. Один и тот же кластер может обслужить и быстрый log-write (ONE), и критичный financial-write (QUORUM/ALL).
pc-ec-mongo-partition — MongoDB при partition. Меняем сетевую погоду: cross-DC и cross-region линки падают. MongoDB с writeConcern: majority определяет, что у нас на стороне есть majority (2 из 4), и продолжает принимать writes. На minority-стороне primary step down, реплика уходит в read-only. Урок: PC-системы при partition жертвуют доступностью на minority-стороне, чтобы не допустить split-brain. Это правильное поведение для систем, где «соврать» хуже, чем «отказать».
pc-ec-spanner-truetime — Google Spanner. Самый дорогой и самый строгий сценарий. Spanner использует TrueTime API (синхронизированные часы через GPS+atomic clocks) и 2PC через регионы. Каждый commit включает commit-wait — паузу на величину uncertainty interval (~7ms), чтобы гарантировать external consistency. Общий round-trip — ~90ms. Урок: PC/EC в global scale достижим, но платишь за это infrastructure (atomic clocks в каждом DC) и latency на каждом write.
ADR-001: PACELC формализует двойственный trade-off. Когда Эрик Брюер опубликовал CAP в 2000, индустрия восприняла её как «выбери два из трёх». Это породило мем «нам нужна AP-система», на котором сидели маркетинг-материалы Cassandra и Riak. Проблема — что в нормальной работе нет никакого выбора между A и C: партиции нет, доступны все реплики. Реальный выбор — между latency и consistency. Daniel Abadi в 2010 указал на эту дыру и предложил расширение: PACELC. Теперь Cassandra правильно классифицируется как PA/EL (при partition доступна, в норме экономит latency за счёт consistency), а Spanner — как PC/EC (при partition отдаёт consistency, и в норме тоже).
Что мы теряем, принимая PACELC? Ничего — это надмножество CAP. Что выигрываем? Возможность сравнивать системы, которые по CAP неотличимы. DynamoDB default и Cassandra default обе AP, но обе ещё и EL — то есть в норме оптимизируют latency. Spanner и etcd обе CP, но обе ещё и EC — то есть в норме платят latency за линеаризуемость. Без второй буквы Discord (Cassandra) и Stripe (Spanner-подобные системы) выглядят одинаково — а они принципиально разные продукты по UX и latency-бюджету.
Когда классификация ломается? Когда система tunable per-query (Cassandra, MongoDB, Cosmos DB). Тогда правильный ответ — «класс зависит от настройки». MongoDB с default writeConcern: majority это PC/EC; та же MongoDB с writeConcern: 1 + readPreference: secondaryPreferred это PA/EL. Это не баг классификации, а свойство современных БД: они продают вам не точку, а ползунок.
LOCAL_QUORUM/LOCAL_ONE, оба EL-leaning.writeConcern: majority. При partition minority-сторона делает primary stepdown и уходит в read-only. Tunable: можно превратить в PA/EL через writeConcern: 1 + secondary reads, но это сознательный downgrade.consistency=ALL для всех writes — и получает PC/EC в латентности без гарантий PC/EC при partition (Cassandra на partition всё равно AP). Худшее из двух миров: высокая latency и stale reads.PACELC — это lens для сравнения stateful distributed datastores с replication. Для stateless web-сервера PACELC не применима: у него нет shared state, нет реплик, нет partition-сценария. Для single-node SQLite или embedded RocksDB — тоже не применима: одна нода — некого синхронизировать.
Для систем, где consistency не определена (полнотекстовый поиск, рекомендации, ML-inference) PACELC тоже мало помогает: вопрос не «strong vs eventual», а «свежий индекс vs устаревший». Здесь полезнее метрики свежести данных (data freshness SLO), а не категориальная классификация.
Если ваш бизнес-кейс не требует мульти-DC или мульти-региональной репликации, PACELC становится теоретическим упражнением. Single-primary Postgres внутри одного DC — это просто «PostgreSQL», без необходимости приписывать ему класс.
После этого урока логично перейти к ::concept{slug="cap-theorem"} (если ещё не читали), а дальше — к моделям консистентности (linearizability, serializability, snapshot isolation), которые объясняют, что именно стоит за буквой C.