«Управляемый» (managed) сервис — это когда вы пользуетесь технологией, а её обслуживанием занимается провайдер. Своя база на сервере — это вы сами ставите PostgreSQL, настраиваете копии, по ночам чините. Управляемая база — та же PostgreSQL, но копии, замену сломанного узла и обновления делает Azure. Вы платите за это деньгами, но не временем и не бессонными ночами.

Главная ценность облака для backend-разработчика — не виртуальные машины, а именно управляемые данные: базы, кэши, очереди и брокеры. Эта статья — карта соответствий «то, что вы знаете по своему серверу → как это называется в Azure», и честный список того, что managed-сервис за вас не делает.

ваш сервис Azure Database for PostgreSQL пулер и приватный доступ Azure Managed Redis TTL и политика вытеснения Service Bus темы, DLQ, дедупликация Event Hubs разделы и группы потребителей

Четыре управляемых хранилища и то, что остаётся вашим у каждого: размер пула и способ подключения у базы, сроки жизни и политика вытеснения у кэша, идемпотентность у очереди, число разделов у потока.

Обязательно

Azure Database for PostgreSQL

Azure Database for PostgreSQL — тот же PostgreSQL, только вокруг него автоматика: резервные копии с восстановлением на момент в прошлом, зоно-избыточная высокая доступность, обновления версий в заданное окно. Аналог RDS в AWS. Полное имя сервиса — Flexible Server, и выбирать тут не из чего: прежний вариант Single Server выведен из эксплуатации, так что Single Server в старой документации — уже история.

Главное для новичка: managed-база снимает с вас эксплуатацию железа, но не проектирование данных. Она спасёт от сгоревшего диска, но не от запроса SELECT без индекса, перебирающего миллион строк. Схема, индексы, блокировки, безопасные миграции, тюнинг медленных запросов — по-прежнему ваша работа.

Грабли, на которые наступают почти все, — лимит соединений: у базы есть максимум одновременных подключений, и десяток приложений со своими пулами выедают его незаметно. Лечится дисциплиной размеров пулов и встроенным пулером — PgBouncer. Только это не галочка «включил и забыл»: его поднимают параметром сервера pgbouncer.enabled, он слушает отдельный порт 6432 (приложение переводят на него), а на самом дешёвом тарифе Burstable его нет вовсе. И грабля при переключении: по умолчанию пулер работает в режиме транзакций, где поддержка подготовленных выражений выключена (pgbouncer.max_prepared_statements = 0), — приложение, которое их использует, на порту 6432 начнёт падать, пока этот параметр не подняли. Рядом в семействе — управляемый MySQL и Azure SQL Database (управляемый SQL Server); модель у всех одинаковая.

Соединения: откуда потолок и почему помогает пулер

«Лимит соединений» — главные грабли управляемой базы, и механику стоит понимать, иначе лечение выглядит магией.

Почему у PostgreSQL есть потолок. Каждое соединение — это отдельный процесс операционной системы со своей памятью (единицы-десятки мегабайт, в зависимости от того, что делает запрос). Сто соединений — это сто процессов; тысяча означает, что память кончится раньше, чем процессор. Поэтому предел (max_connections) в управляемой базе задаётся платформой по объёму памяти выбранного размера: у самых маленьких это десятки соединений, у средних — несколько сотен. Посмотреть своё значение можно запросом SHOW max_connections;, и это первое, что стоит сделать до расчёта пулов.

Как это выедается незаметно. Пять экземпляров приложения по двадцать соединений в пуле — это сто соединений, которые держатся постоянно, даже когда запросов нет. Добавьте конвейер, миграции, инструмент аналитики, чью-то локальную отладку — и потолок близко. Симптом: новые подключения получают отказ too many connections, причём первым отказ получает не тяжёлый сервис, а тот, кто подключился последним.

Почему помогает пулер. Пулер (в управляемом PostgreSQL Azure есть встроенный) держит небольшое число реальных соединений к базе и мультиплексирует через них запросы многих клиентов: пока клиент не выполняет запрос, его соединение к базе не занято. Тысяча клиентов превращается в тридцать процессов на стороне базы.

Оговорка, без которой это ломается: в режиме мультиплексирования по транзакциям (обычный режим пулера) не работают вещи, привязанные к сеансу, — подготовленные запросы на уровне сеанса, временные таблицы, SET на сеанс, рекомендательные блокировки. Часть библиотек доступа к данным использует подготовленные запросы по умолчанию, и это надо либо выключить, либо перевести в режим, который пулер поддерживает.

Что делают на практике: считают сумму пулов по всем потребителям и сверяют с пределом базы (с запасом на служебные подключения), ставят размер пула от нагрузки, а не по привычке (десять соединений на экземпляр — обычно с избытком), включают встроенный пулер там, где потребителей много или они короткоживущие (функции, задачи), и ставят оповещение на число активных соединений — это одна из метрик, которые база отдаёт сама.

Как приложение дотягивается до базы

Выбор способа подключения делается при создании базы и потом не меняется — поэтому решить его надо заранее.

Приватный доступ (интеграция с виртуальной сетью). База получает адрес в вашей подсети и публичного адреса не имеет вовсе. Это правильный вариант для боевого контура: до базы нельзя дотянуться из интернета в принципе, права на сеть решают, кто к ней ходит. Цена: приложение должно быть в той же сети или в связанной — а значит, вариант размещения приложения выбирается вместе с этим решением (об этом статья про вычисления).

Публичный доступ с правилами межсетевого экрана. У базы есть публичный адрес, и доступ разрешён перечисленным диапазонам адресов. Проще в настройке и хуже по двум причинам: адреса исходящего трафика у платформенных сервисов меняются, так что правила приходится держать целыми диапазонами; и одна ошибка в правилах (или отдельная галочка «разрешить доступ сервисам Azure») открывает базу заметно шире, чем вы думали.

Отсюда простое правило: боевая база — приватный доступ, всегда. Публичный оставляют для стендов, где важнее простота, и даже там список разрешённых адресов не должен превращаться в «разрешить всё».

Две детали, которые идут в комплекте. При приватном доступе нужна приватная зона имён, иначе имя базы продолжает разрешаться в публичный адрес — это самая частая поломка, и разбирает её статья про сеть. А шифрование соединения (sslmode=require и проверка сертификата) включают независимо от способа доступа: приватная сеть не отменяет шифрования.

Azure Cache for Redis

Кэш — быстрое временное хранилище, куда кладут уже посчитанный результат, чтобы не считать заново. Azure Cache for Redis — управляемый Redis: кластер, реплики и переключение при сбое настраивает облако. Аналог ElastiCache в AWS.

Для новых проектов смотрите на преемника — Azure Managed Redis. Старую линейку Azure Cache for Redis (тарифы Basic, Standard, Premium) объявили уходящей: с 1 октября 2026 года новые такие кэши создать уже нельзя, а 30 сентября 2028 года оставшиеся отключат. Модель работы та же, меняются название и тарифы.

Применяют как обычный Redis: кэширование ответов с временем жизни (TTL), распределённая блокировка, ограничение частоты запросов. Главное правило новичку: кэш — это не база данных. Данные, потеря которых недопустима (заказы, платежи), в нём не хранят: кэш может сбросить содержимое в любой момент.

Что с кэшем, когда память кончилась

Про кэш сказано «это не база данных», и стоит добавить, что именно происходит при заполнении памяти — потому что от настройки зависит, что вы потеряете.

Политика вытеснения решает, кого удалять, когда память заполнена. Значения разные, и практический выбор — между двумя:

  • allkeys-lru — вытесняется любой ключ, к которому давно не обращались. Правильный выбор для чистого кэша: потеря записи означает лишний запрос к базе, и ничего больше.
  • volatile-lru — вытесняются только ключи со сроком жизни. Правильный выбор, когда в том же кэше лежат вещи, терять которые нельзя молча (например, распределённые блокировки): у них срока жизни нет, и они защищены от вытеснения. Обратная сторона: если ключей без срока жизни станет много, память заполнится ими, и новые записи начнут получать отказ.

Отсюда практическое правило: если в кэше лежит только кэш — allkeys-lru и обязательный срок жизни у всего. Если в кэше живут блокировки, счётчики или что-то ещё важное — либо volatile-lru с дисциплиной, либо, что чище, отдельный экземпляр под такие данные.

И то, что теряется первым при любой политике: то, к чему давно не обращались. Значит, редко используемые, но дорогие в пересчёте значения — плохие кандидаты на кэш без запаса памяти.

Service Bus и Storage Queues

Сервис отправки писем лёг — и вместе с ним лёг заказ, который всего лишь хотел отправить письмо. Очередь развязывает отправителя и получателя: приложение кладёт задачу и идёт дальше, а обработчик разгребает её в своём темпе. Для очередей в Azure два инструмента:

  • Storage Queues — простая очередь: положить задачу, забрать задачу. Годится для базовой разгрузки.
  • Service Bus — полноценный брокер с очередями и темами (topics): темы дают модель «публикация-подписка», когда одно сообщение получают несколько независимых подписчиков; плюс дедупликация, транзакции и упорядочивание. Про порядок важно не обмануться: сам по себе он не гарантируется. Порядок держится либо внутри сессии (сообщения с одним идентификатором сессии достаются одному обработчику и идут подряд), либо когда получатель ровно один. Поставили рядом несколько конкурирующих обработчиков ради скорости — порядок сломался. Это выбор для серьёзной обработки сообщений.

Так сглаживают всплески и не теряют задачи при недоступности обработчика. Service Bus часто служит триггером для Azure Functions.

Event Hubs

Когда нужна не очередь задач, а поток событий, который читают несколько независимых потребителей и перечитывают историю, берут Event Hubs — сервис потоковой передачи, к которому можно подключиться по протоколу Apache Kafka. Здесь легко ошибиться с аналогией: это не управляемая Kafka, а собственный движок Azure, умеющий разговаривать по её протоколу. Часть кафкиных возможностей на нём недоступна: точки входа Kafka нет на базовом тарифе, транзакции и Kafka Streams живут только на старших. По модели он ближе к Kinesis Data Streams из AWS, чем к MSK — настоящая Kafka в AWS это как раз MSK. Разницу между очередью и брокером-логом и устройство Kafka разбирает раздел Kafka.

Управляемый против своего: как выбирать

УправляемыйСвой на сервере
ЭксплуатацияКопии, переключение, обновления — облакоВсё ваше, включая три часа ночи
ЦенаНадбавка к стоимости железаДешевле железом, дороже людьми
КонтрольВерсии и параметры из списка облакаЛюбые расширения и тонкая настройка

Разумное правило: компоненты с состоянием (базы, кэши, очереди) берём управляемыми, пока нет конкретной причины делать иначе. Прежде чем самому обслуживать базу при доступном managed-сервисе, честно ответьте, на что команда потратит время, которое сервис ей освобождает.

Где это применяется

Управляемые данные — костяк почти любого сервиса: база под основные данные, кэш перед ней, очередь для фоновых задач, брокер для событий. Всё это живёт во внутренней сети без публичных адресов и доступно приложению через managed identity.

Типичные ошибки новичков:

  • хранят важные данные в кэше — теряют при сбросе;
  • выедают лимит соединений к базе без пулера;
  • берут свой сервер там, где хватило бы managed;
  • дают базе публичный IP ради удобства — открывают её сканерам.
Дополнительно: при первом чтении можно пропустить

Глубже: реплики, обслуживание и обрывы соединенийрасширенное

Три свойства управляемой базы, о которых узнают в неподходящий момент.

Реплики для чтения. Управляемый PostgreSQL умеет создавать реплики, и с них можно читать — отчёты, аналитику, тяжёлые выборки. Две оговорки: реплика асинхронная, то есть данные на ней отстают (обычно миллисекунды, под нагрузкой больше), и приложение должно знать, что читать с неё можно не всё — прочитать только что записанное с реплики нельзя. Подключение к реплике — это отдельный адрес, то есть в приложении появляется второй источник данных и решение «какой запрос куда».

Окно обслуживания. Платформа обновляет базу (версии, исправления безопасности) в заданное окно — день недели и час, которые вы выбираете сами. Это лучше, чем «когда угодно», и это по-прежнему означает перерыв: обновление обычно перезапускает сервер.

И главное: обслуживание и переключение рвут соединения. Плановое обновление, переключение на резервный экземпляр при отказе зоны, масштабирование размера — всё это означает, что открытые соединения обрываются, а адрес остаётся тем же. Приложение обязано это переживать: пул должен обнаруживать мёртвые соединения и открывать новые, а запросы — повторяться на ошибке соединения (но не на ошибке выполнения, иначе повторится то, чего повторять нельзя).

Что настраивают в приложении, чтобы обслуживание проходило незаметно: проверку соединения перед выдачей из пула, ограничение времени жизни соединения (чтобы пул сам обновлял их), таймауты на подключение и на запрос, и повтор на ошибках соединения с небольшой паузой. Без этого плановое обслуживание в три часа ночи превращается в утренний разбор «почему сервис не поднялся сам».

Глубже: лавина одинаковых промаховрасширенное

Отдельная беда, которая случается ровно в момент, когда кэш нужнее всего. Популярный ключ истёк; в ту же секунду сто параллельных запросов не находят его в кэше — и все сто идут считать одно и то же в базу. База получает стократную нагрузку на ровном месте, отвечает медленно, запросы копятся, и дальше по знакомому сценарию.

Три приёма, которые это лечат:

Блокировка на пересчёт. Первый, кто обнаружил промах, берёт короткую блокировку (в том же кэше) и считает; остальные либо ждут результата, либо отдают чуть устаревшее значение. Реализуется в десять строк и закрывает самый острый случай.

Обновление до истечения. Ключ хранится с двумя сроками: «свежий до» и «годен до». Пока значение свежее, отдаём его; когда свежесть кончилась, но срок не вышел, — отдаём старое значение и запускаем пересчёт в фоне. Пользователь никогда не ждёт пересчёта, а лавины нет по определению.

Разброс сроков жизни. Если сто ключей записаны одновременно с одинаковым сроком, они и истекут одновременно. Добавление случайной добавки к сроку (скажем, ±10 %) размазывает истечение по времени — приём копеечный и работает.

Плюс общая мера, которая помогает и здесь: ограничение параллельных обращений к базе из приложения. Тогда даже лавина промахов не превращается в сто одновременных запросов.

Глубже: числа, по которым выбирают очередьрасширенное

Разница между простой очередью хранилища и служебной шиной сводится к нескольким конкретным пределам, и вот они.

СвойствоStorage QueueService Bus (Standard)
Максимальный размер сообщения64 КБ256 КБ (у Premium — до 100 МБ)
Срок хранения сообщенияпо умолчанию 7 дней (настраивается)по умолчанию 14 дней
Порядок сообщенийне гарантируетсягарантируется внутри сеанса
Очередь недоставленныхнет (делают руками отдельной очередью)встроенная
Темы и подписки (один ко многим)нетесть, с фильтрами
Транзакции и дедупликациянетесть
Ценаза операции, очень дёшевоза операции плюс уровень, дороже

Как этим пользоваться при выборе. Простая очередь задач внутри своего сервиса, сообщения маленькие, порядок не важен — очередь хранилища: дешевле и проще некуда. Нужен порядок, очередь недоставленных из коробки, темы с подписками, дедупликация или сообщения больше 64 КБ — служебная шина.

И правило про размер, которое действует в обоих случаях: в сообщении едет ссылка, а не данные. Файл, изображение, большой отчёт кладут в хранилище объектов, а в сообщении передают путь. Тогда предел размера перестаёт быть ограничением вовсе, а очередь остаётся быстрой.

Глубже: Event Hubs: что нужно знать, кроме «это как Kafka»расширенное

Отсылки к статье про Kafka мало, потому что решения принимаются по четырём понятиям, и у них здесь свои имена.

Разделы (partitions). Поток делится на разделы, и это единица параллелизма: сообщения одного раздела читаются по порядку одним читателем. Число разделов задают при создании и обычно не меняют — значит, его считают заранее, от нужной пропускной способности и числа читателей. Правило то же, что в Kafka: разделов не меньше, чем планируется параллельных обработчиков.

Группы потребителей (consumer groups). Каждая группа читает поток независимо и держит своё положение. То есть один поток событий обслуживает и обработку заказов, и аналитику, и архивирование — каждый в своём темпе и со своим отставанием. Добавление новой группы не мешает существующим.

Срок хранения. События живут заданное время (у обычного уровня от одного до семи дней) и удаляются независимо от того, прочитал их кто-нибудь или нет. Отсюда практическое следствие: отставание читателя опаснее, чем кажется — если он отстанет больше срока хранения, данные уедут безвозвратно. Отставание группы — главная метрика, на которую ставят сигнал.

Единицы пропускной способности. Ёмкость покупается единицами, каждая даёт свой предел на приём и на отдачу в секунду (и по объёму, и по числу событий). Превышение — не отказ навсегда, а ограничение частоты: отправитель получает отказ и должен повторить. Единицы можно менять и можно включить автоматическое увеличение — это одна настройка, и её стоит включить, чтобы всплеск не превращался в потерю событий на отправителе.

Отдельно стоит знать про захват в хранилище (Capture): поток можно автоматически складывать в хранилище объектов файлами — дешёвый архив всех событий без единой строки кода. Это тот ответ, который нужен, когда «хотим хранить события год», а срок хранения потока — семь дней.

И выбор между потоком событий и очередью, если коротко: очередь — это задачи для одного получателя, которые исчезают после обработки; поток — это факты, которые читают несколько независимых подсистем и которые можно перечитать. Подробное сравнение двух моделей — в статье про выбор между брокерами.

Коротко

  • Управляемый PostgreSQL снимает эксплуатацию железа, но не проектирование данных: копии, зоно-избыточная доступность и окно обновлений у облака, схема, индексы и размер пула ваши.
  • Соединение это процесс с памятью, и пулы пяти экземпляров выедают потолок незаметно: считают сумму пулов, ставят размер от нагрузки и включают встроенный пулер, помня, что в режиме по транзакциям не работает сеансовое.
  • Способ подключения выбирают при создании и потом не меняют: боевая база с приватным доступом и приватной зоной имён, публичный доступ по адресам только для стендов.
  • Реплики для чтения асинхронные и отстают, окно обслуживания это перезапуск, а обслуживание и переключение рвут соединения: проверка соединения перед выдачей, ограничение срока жизни, таймауты и повтор при обрыве.
  • Кэш это не база: для нового проекта Azure Managed Redis, allkeys-lru и обязательный срок жизни для чистого кэша, volatile-lru, если рядом живут блокировки.
  • Лавину одинаковых промахов гасят блокировкой на пересчёт, обновлением до истечения, разбросом сроков жизни и ограничением параллельных обращений к базе.
  • Storage Queue дёшев и прост для задач без порядка, Service Bus даёт темы с подписками, очередь недоставленных, порядок в сеансе, транзакции и дедупликацию; в сообщении едет ссылка, а не файл.
  • Event Hubs это поток фактов для нескольких независимых читателей: разделы задают параллелизм и не меняются, группы потребителей держат своё положение, срок хранения удаляет непрочитанное, ёмкость покупается единицами, Capture складывает поток в хранилище.
  • Компоненты с состоянием берут управляемыми, пока нет конкретной причины делать иначе, и считают полную цену владения.

Что почитать дальше