ТакПростоТакПросто.ai
ЦеныДля бизнесаОбразованиеДля инвесторов
ВойтиНачать

Продукт

ЦеныДля бизнесаДля инвесторов

Ресурсы

Связаться с намиПоддержкаОбразованиеБлог

Правовая информация

Политика конфиденциальностиУсловия использованияБезопасностьПолитика допустимого использованияСообщить о нарушении
ТакПросто.ai

© 2026 ТакПросто.ai. Все права защищены.

Главная›Блог›Настройка производительности Go и Postgres: плейбук для API
16 дек. 2025 г.·8 мин

Настройка производительности Go и Postgres: плейбук для API

Настройка производительности Go и Postgres: пул соединений, планы запросов, индексы, пагинация и JSON-ответы. Проверки перед первыми пользователями.

Настройка производительности Go и Postgres: плейбук для API

Какие тормоза обычно появляются у новых API

Новые API редко тормозят из-за одной большой ошибки. Чаще это набор мелких решений, которые в сумме дают рост задержек, а потом внезапные таймауты.

У AI-сгенерированных ручек есть типичный перекос: они стараются быть "умными" и делают слишком много работы за один запрос. Самое частое - несколько лишних походов в базу (N+1), дополнительные проверки прав на каждую строку, запросы "на всякий случай", а иногда и повторное чтение одной и той же сущности в разных местах обработчика.

Симптомы обычно выглядят так:

  • p95 и p99 растут быстрее, чем средняя задержка
  • всплески CPU на приложении или на Postgres без видимого роста трафика
  • много ожидания соединений к базе (очередь в пуле)
  • редкие, но массовые таймауты при пиках
  • сеть и ответы становятся тяжелыми, хотя данные "те же"

По узким местам картина чаще всего делится на три зоны. База данных: плохой план запроса, отсутствие нужного индекса, слишком широкие SELECT, блокировки. Сеть: большие JSON-ответы, лишние поля, отсутствие сжатия на уровне инфраструктуры. Сериализация: вы отдаете массивы из тысяч объектов, и CPU тратится на сборку структуры, маршалинг и копирование.

Простой пример: ручка "список заказов" сначала выбирает 50 заказов, а потом для каждого отдельно тянет клиента и статус. На тестовых данных это незаметно, но с реальной базой получаются 101 запрос, рост p95 и постоянные пики нагрузки.

До первого трафика важнее всего исправить вещи, которые могут сломать сервис сразу: адекватный пул соединений в Go, лимиты на запросы и таймауты, защита от случайной выдачи "всего" без пагинации, базовые индексы под самые частые фильтры.

А вот тонкую полировку можно отложить: идеальная форма JSON для всех клиентов, микропобеды в аллокациях, рефакторинг схемы. Если вы собираете API в TakProsto и потом экспортируете код, эти ранние проверки особенно полезны: они ловят "слишком много запросов" еще до того, как появятся реальные пользователи.

Быстрые проверки перед первыми реальными пользователями

Перед тем как начинать тонкую настройку производительности Go и Postgres, соберите минимум цифр. Без них вы будете менять параметры вслепую и спорить, что именно «стало быстрее».

Первый набор метрик, который стоит иметь под рукой:

  • p50 и p95 времени ответа (по основным ручкам)
  • RPS (сколько запросов в секунду держите без деградации)
  • процент ошибок (5xx, таймауты, отмены запросов)
  • активные соединения к Postgres (и сколько из них занято)
  • список самых медленных запросов (top по времени и по частоте)

Дальше сделайте простую нагрузочную проверку: выберите 1-2 самых важных эндпоинта и постепенно увеличивайте параллельность (например, 10, 25, 50, 100 одновременных запросов). Цель не «побить рекорд», а найти точку, где p95 резко растет или появляются ошибки. Часто сюрприз в том, что сервер по CPU еще жив, а база уже захлебнулась из-за очереди на соединения или блокировок.

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

Минимальный набор таймаутов в API, чтобы не зависать бесконечно:

  • таймаут запроса на уровне HTTP сервера
  • дедлайн на обработку запроса через context
  • таймаут на запрос к базе (и отдельный на транзакцию)
  • ограничение на максимальный размер ответа и тела запроса

Простой сценарий: у вас есть эндпоинт списка. Без таймаутов и лимитов один «тяжелый» запрос может занять все соединения к базе, и остальные начнут ждать. С таймаутами и ограничениями сервис скорее вернет понятную ошибку, чем уронит весь API.

Пул соединений в Go: настройка без догадок

В Go объект sql.DB часто путают с одним подключением к базе. На самом деле это менеджер пула: он хранит и переиспользует соединения, открывает новые до лимита и раздает их горутинам. Если лимиты не заданы, сервис может внезапно упереться в очередь ожидания соединения или, наоборот, открыть слишком много подключений и «прибить» Postgres.

Базовая настройка занимает пару минут и уже сильно помогает, когда вы делаете настройку производительности Go и Postgres перед первым трафиком.

Быстрая настройка: 3 параметра, которые реально важны

Начните с простых значений и меняйте их только после измерений:

// db, _ := sql.Open("pgx", dsn)

db.SetMaxOpenConns(20)          // верхняя граница одновременных соединений

db.SetMaxIdleConns(10)          // сколько держать «теплыми» без работы

db.SetConnMaxLifetime(30 * time.Minute) // обновлять соединения, чтобы не копить «старые»

Как подобрать числа:

  • MaxOpenConns задавайте от лимита Postgres на соединения и количества инстансов вашего API. Если в Postgres доступно 100 соединений, а у вас 4 реплики сервиса, то 20-25 на реплику обычно безопаснее, чем «как получится».
  • MaxIdleConns держите меньше MaxOpenConns. Идея простая: прогревать частые запросы, но не занимать соединения впрок.
  • ConnMaxLifetime полезен в долгоживущих сервисах: иногда сетевые условия меняются, соединения «подвисают», и обновление по времени снижает шанс странных ошибок.

Главный сигнал, что пул настроен плохо: время ответа растет, а база при этом не перегружена. Часто причина в том, что запросы стоят в очереди за свободным соединением.

Что логировать, чтобы не гадать

Добавьте метрики и логи хотя бы на уровне обработки запроса:

  • общее время запроса к БД и число строк в ответе
  • время ожидания соединения из пула (сколько запрос простоял до начала выполнения)
  • количество ошибок таймаута и повторов (ретраев)
  • текущие значения пула (open, in-use, idle)

Пример из практики: при генерации API (например, в TakProsto) легко получить несколько параллельных запросов на один экран. Если пул маленький, все упрется в ожидание соединения. Если слишком большой, Postgres начнет тратить время на переключение контекста и память, и станет хуже всем.

Лимиты и защита Postgres от перегруза соединениями

Слишком много соединений к Postgres почти всегда делает хуже. Каждое соединение - это память, процессы и переключения контекста. Когда сервис под нагрузкой открывает сотни коннектов, база начинает тратить силы не на запросы, а на обслуживание «толпы».

Первая цель в настройке производительности Go и Postgres - понять, сколько соединений реально нужно вашему API. Часто достаточно десятков, а не сотен: если запросы быстрые и индексированные, один коннект успевает обслужить много запросов подряд.

Быстрая проверка занимает пару минут. Важно смотреть не только max_connections, но и реальное число активных сессий и ожиданий:

  • Узнайте лимит: SHOW max_connections;
  • Посмотрите, сколько сессий сейчас: SELECT count(*) FROM pg_stat_activity;
  • Найдите «залипшие» транзакции: SELECT pid, state, now()-xact_start AS age, query FROM pg_stat_activity WHERE xact_start IS NOT NULL ORDER BY age DESC LIMIT 5;
  • Проверьте, есть ли очередь ожиданий (lock/wait): поле wait_event в pg_stat_activity

Если вы видите всплески соединений и короткие запросы, которые начинают ждать, часто помогает PgBouncer. Он решает конкретную проблему: много коротких подключений от приложения. PgBouncer держит небольшой пул коннектов к Postgres и раздает их запросам, а не заставляет базу создавать новые процессы на каждый чих.

Даже при нормальном пуле бывают «зависания», которые тихо съедают коннекты. Поставьте ограничители, чтобы база сама чистила проблемные случаи: statement_timeout (чтобы не выполнялись бесконечные запросы) и idle_in_transaction_session_timeout (чтобы транзакции не висели без дела, держа блокировки). Типичный сценарий - обработчик открыл транзакцию, а потом ждет внешний вызов или упал до коммита. Такие сессии незаметно забивают лимит соединений и тормозят всех.

Если вы собираете API в TakProsto и планируете рост нагрузки, договоритесь о простом правиле: соединений меньше, чем кажется нужным, и таймауты включены по умолчанию. Это дешевле, чем искать «куда делись коннекты» в день запуска.

Планы запросов: как читать EXPLAIN и что менять

Запустите деплой и проверку
Разверните приложение и проверьте поведение под параллельной нагрузкой до первых пользователей.
Развернуть

Когда API начинает тормозить, гадать бесполезно. Самый быстрый способ понять, почему запрос медленный, это посмотреть план. Для настройки производительности Go и Postgres это почти всегда первый полезный шаг, особенно если эндпоинт сгенерирован быстро (например, в TakProsto) и вы еще не успели проверить, что реально делает база.

Порядок действий простой: найдите конкретный медленный эндпоинт, выпишите SQL, подставьте типичные параметры и запустите план с фактическим временем.

EXPLAIN (ANALYZE, BUFFERS)
SELECT id, title, created_at
FROM posts
WHERE user_id = $1
ORDER BY created_at DESC
LIMIT 20;

В плане ищите несколько красных флагов. Они часто прямо указывают, что менять:

  • Seq Scan по большой таблице: обычно не хватает индекса по условиям фильтра.
  • Sort (особенно с большим числом строк): нет индекса под ORDER BY, или сортировка происходит после JOIN.
  • Nested Loop с большим количеством повторов: один из JOIN возвращает слишком много строк, и база крутит цикл тысячи раз.
  • Actual rows сильно больше/меньше, чем estimated rows: статистика устарела или условия плохо подходят под индекс.
  • Buffers: много чтений с диска, хотя вы ожидали кеш.

Фраза "строк больше, чем ожидалось" опасна тем, что оптимизатор выбирает план, рассчитанный на маленький результат. В реальности он получает в 10-100 раз больше строк, и внезапно "быстрый" Nested Loop превращается в убийцу latency.

Что обычно помогает без переписывания всего сервиса:

  • Уточнить условия: убрать лишние OR, привести типы (не сравнивать text с uuid), не оборачивать колонку в функции.
  • Поменять порядок JOIN или сделать фильтрацию раньше (например, через подзапрос с LIMIT).
  • Выбирать только нужные поля (особенно если таблица широкая).
  • Добавить индекс под фильтр и сортировку (часто составной: (user_id, created_at DESC)).
  • Обновить статистику (ANALYZE) после загрузок и миграций.

Мини-проверка: если запрос с LIMIT 20 все равно читает сотни тысяч строк, проблема почти всегда в индексе или в порядке выполнения (сортировка и JOIN происходят слишком рано).

Индексы для API: простые правила, которые работают

Большинство «тормозов» в Postgres для API начинается не с Go, а с того, что база вынуждена читать слишком много строк. Правильные индексы почти всегда дают самый быстрый и понятный выигрыш, особенно когда вы делаете настройка производительности Go и Postgres перед первыми реальными пользователями.

Почти всегда нужны индексы по тем полям, по которым вы фильтруете и связываете данные. Если в запросах есть WHERE status = ..., WHERE user_id = ..., WHERE created_at >= ..., то без индекса база часто скатывается в последовательное чтение таблицы. Отдельно проверьте внешние ключи: Postgres не создает индекс автоматически на колонке-ссылке. Если у вас часто ищут «все заказы пользователя», индекс на orders(user_id) обязателен.

Составные индексы: порядок колонок решает

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

Например, типичный запрос списка: WHERE user_id = $1 AND status = $2 ORDER BY created_at DESC LIMIT 20. Для него часто хорошо работает индекс (user_id, status, created_at DESC). Если же status редко используется, лучше (user_id, created_at DESC).

Индексы для сортировки и пагинации

Если вы сортируете по created_at и делаете пагинацию, индекс должен поддерживать этот порядок. Тогда Postgres может читать строки уже в нужной сортировке и не тратить время на лишний Sort.

Проверьте себя по короткому чек-листу:

  • Есть индекс под самые частые WHERE фильтры.
  • Есть индекс на колонках внешних ключей (на стороне «много»).
  • Для списков есть индекс, который совпадает с ORDER BY.
  • Для выборок «за период» есть индекс по дате/времени.
  • Составные индексы повторяют реальный шаблон условий, а не «все подряд».

Важно не переборщить. Каждый индекс занимает место и замедляет INSERT/UPDATE/DELETE, потому что его тоже нужно обновлять. Хорошая практика: добавлять индекс под конкретный медленный запрос, а не «на всякий случай». В проектах, которые быстро собирают через TakProsto, это особенно полезно: вы быстро видите реальные запросы и добавляете только то, что действительно нужно.

Пагинация без сюрпризов: OFFSET vs keyset

OFFSET выглядит удобно: LIMIT 50 OFFSET 5000 и готово. Проблема в том, что Postgres все равно должен “пройти” первые 5000 строк, чтобы отдать следующие 50. На маленьких таблицах вы этого не заметите, но по мере роста данных задержка увеличивается, а нагрузка на CPU и диск становится неприятной. Для API, особенно с автогенерированными эндпоинтами, это частая причина “внезапных” тормозов.

Keyset (cursor) пагинация работает иначе: вы не просите “страницу номер N”, вы просите “все, что идет после последней записи, которую я видел”. Тогда база использует индекс и сразу прыгает в нужное место.

Пример для сортировки по времени создания, со стабильным порядком (важно добавлять второе поле, чтобы не было дублей при одинаковом created_at):

-- первая страница
SELECT id, created_at, title
FROM items
WHERE user_id = $1
ORDER BY created_at DESC, id DESC
LIMIT $2;

-- следующая страница (передаем last_created_at и last_id с предыдущей)
SELECT id, created_at, title
FROM items
WHERE user_id = $1
  AND (created_at, id) < ($3, $4)
ORDER BY created_at DESC, id DESC
LIMIT $2;

Такой подход дает три важных эффекта: скорость почти не зависит от глубины, порядок стабильный, и между страницами не появляются дубли. Без tie-breaker (например, только created_at) вы рискуете увидеть повторяющиеся записи или пропуски, особенно если новые строки активно добавляются.

Чтобы это работало предсказуемо, держите простые правила:

  • Всегда фиксируйте ORDER BY и добавляйте уникальный “хвост” (обычно id).
  • Возвращайте клиенту курсор (пара значений или упакованную строку) вместе со списком.
  • Выбирайте размер страницы по умолчанию 20-50, а максимальный limit жестко ограничивайте (например, 100-200).
  • Для тяжелых списков сначала отдавайте только нужные поля, без “полных объектов”.

Если вы делаете API на Go + Postgres (в том числе в TakProsto), keyset-пагинация обычно дает самый быстрый выигрыш без сложного тюнинга: запросы становятся короткими, индексами пользоваться легче, а задержки не растут вместе с номером страницы.

JSON-ответы: меньше работы и меньше байт

Поймайте узкие места заранее
Сгенерируйте код и заранее пройдитесь по запросам, индексам и размеру JSON ответов.
Попробовать

JSON часто становится скрытым тормозом: база читает лишнее, приложение тратит CPU на сборку структуры, а сеть гоняет килобайты, которые клиент даже не использует. В настройке производительности Go и Postgres это один из самых быстрых способов выиграть время отклика.

Первое правило простое: не тяните лишние колонки. Если на экране списка нужны id, name, status и updated_at, не выбирайте description, большие текстовые поля и тем более JSONB с деталями. Делайте отдельные DTO для списка и для карточки. Это уменьшает и нагрузку на Postgres, и работу сериализации в Go.

Где формировать JSON: в приложении или в Postgres? Обычно проще поддерживать сборку в Go: вы видите типы, проще тестировать, легче менять формат. Генерация JSON в Postgres (json_build_object, агрегации) полезна, когда нужно собрать вложенные структуры одним запросом и вы точно контролируете план, но цена ошибки выше: сложнее читать запросы и легко случайно сделать тяжелую агрегацию.

Чтобы ответ был меньше, начните с формы данных:

  • Снижайте вложенность, если клиенту не нужны глубокие деревья (лучше отдельный запрос за деталями).
  • Не дублируйте одно и то же поле в разных местах объекта.
  • Возвращайте числа и даты в стабильном формате, без лишних строковых полей вроде "pretty".
  • Включайте компрессию на сервере (gzip или brotli), особенно для списков.

Пример: список из 50 сущностей. Если вы отдаете полный объект с 20 полями и вложенным meta, ответ может быть 80-150 КБ. Если оставить 5-6 полей для списка и сжать, часто получается 10-30 КБ. Разница заметна даже на локальной сети.

Кэширование на уровне API помогает, но не все можно кэшировать безопасно. Хорошо кэшируются публичные справочники, неизменяемые конфиги, списки без персональных данных. Осторожнее с ответами, зависящими от пользователя, ролей и времени: кэш нужно ключевать по параметрам, языку, правам и версии данных. В TakProsto, где API часто генерируются быстро, добавьте простое правило: кешируйте только то, что вы готовы отдавать любому пользователю при тех же параметрах запроса, и задавайте короткий TTL, пока нагрузка не стала предсказуемой.

Частые ошибки и ловушки при тюнинге Go + Postgres

Самая частая причина внезапных тормозов - не «медленный Postgres», а несколько мелких решений, которые вместе превращают API в перегретую систему. При настройке производительности Go и Postgres полезно сначала проверить типовые ловушки и убрать их до того, как придут первые реальные пользователи.

Пул соединений, который атакует вашу же базу

Слишком большой пул в Go выглядит безопасно: «пусть будет побольше, чтобы не ждать». На деле это часто эффект «сам себе DDoS». Когда каждый запрос к API может занять соединение, база начинает тратить время на планирование, контекстные переключения и ожидания, а не на полезную работу.

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

N+1 запросов, особенно после генерации кода

N+1 часто появляется незаметно, когда вы берете список сущностей, а потом для каждой подгружаете связанные данные отдельным запросом. В vibe-coding платформах это может всплыть и в сгенерированном коде, если структура ответа задумывалась «как в UI», а не «как в SQL».

Мини-сценарий: эндпоинт /orders отдает 50 заказов, а затем для каждого делает запрос за пользователем и суммой. Получается 101 запрос вместо 1-2, и задержка растет не плавно, а ступенькой.

Нет лимитов и есть тяжелые фильтры

Если endpoint принимает limit без верхней границы, вы сами разрешаете клиенту запросить «все сразу». То же с фильтрами: поиск по неиндексированному полю или сортировка по вычисляемому значению быстро превращаются в полный скан таблицы.

Долгие транзакции и забытые блокировки

Долгая транзакция удерживает ресурсы и может блокировать других. Частая ошибка - открыть транзакцию, сделать несколько запросов, а затем ждать внешнего ответа. Еще хуже - забытый SELECT ... FOR UPDATE, который нужен только при реальном конфликте записи.

Смешивание чтения и записи без необходимости

Часто логика «прочитать, посчитать, обновить счетчик» делается одним большим запросом или транзакцией «на всякий случай». Если обновление можно вынести отдельно или делать реже, вы уменьшите блокировки и нагрузку на WAL.

Короткий чек перед запуском:

  • Ограничьте max limit и валидируйте сортировки и фильтры.
  • Проверьте, сколько SQL-запросов делает один HTTP-запрос.
  • Убедитесь, что транзакции живут миллисекунды, а не секунды.
  • Не держите FOR UPDATE там, где нет гонки на запись.
  • Сведите запись (счетчики, логи) к минимально необходимому.

Пример: список сущностей в API до и после оптимизации

Перенесите проект в код
Когда логика устоится, выгрузите исходники и продолжайте тюнинг на своей инфраструктуре.
Экспортировать код

Представим эндпоинт /orders: список заказов с фильтром по статусу и диапазону дат. Такой запрос часто появляется в первых версиях API (в том числе в сгенерированных сервисах на Go + PostgreSQL), и именно на нем быстро всплывают проблемы с p95.

До оптимизации типичная реализация выглядит так: пагинация через OFFSET, выборка SELECT *, а для каждой строки еще делаются дополнительные запросы (например, чтобы подтянуть пользователя или позиции заказа). На маленьких данных все быстро, но после роста таблицы p95 начинает прыгать, а база тратит время на пропуск строк и лишний ввод-вывод.

Вот что меняем.

-- До
SELECT *
FROM orders
WHERE status = $1
  AND created_at >= $2 AND created_at < $3
ORDER BY created_at DESC
LIMIT $4 OFFSET $5;

-- После (keyset)
SELECT id, status, created_at, total_sum
FROM orders
WHERE status = $1
  AND created_at >= $2 AND created_at < $3
  AND (created_at, id) < ($4, $5)
ORDER BY created_at DESC, id DESC
LIMIT $6;

-- Индекс под запрос
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_orders_status_created_id
ON orders (status, created_at DESC, id DESC);

Смысл правок простой: keyset пагинация не заставляет Postgres «пролистывать» тысячи строк, индекс совпадает с фильтрами и сортировкой, а узкий SELECT уменьшает работу по чтению и сборке JSON-ответа.

Быстрая проверка «стало лучше» перед реальными пользователями:

  • EXPLAIN (ANALYZE, BUFFERS) показывает, что используется индекс и падает число прочитанных страниц.
  • Время запроса и p95 на одинаковом наборе тестовых данных заметно ниже.
  • На нагрузке меньше активных соединений и меньше ожиданий по CPU/IO.
  • Размер ответа в байтах уменьшается, а значит быстрее сеть и клиент.

Если вы собираете API в TakProsto, полезно сохранить этот сценарий как шаблон: список почти всегда лучше начинать с keyset + правильного индекса + минимального набора полей.

Следующие шаги: закрепить настройки и не откатиться назад

Хорошая настройка производительности Go и Postgres обычно ломается не из-за "плохого Postgres", а из-за мелких изменений в новых эндпоинтах. Поэтому цель после тюнинга простая: зафиксировать базовые правила и сделать так, чтобы команда нарушала их как можно реже.

Перед релизом пройдитесь по короткому чек-листу. Он занимает 10 минут, но спасает от типовых провалов на первых пользователях:

  • Пул соединений в Go настроен осознанно: max open, max idle, время жизни соединений, контекстные таймауты на запрос.
  • В Postgres есть лимиты от перегруза: max_connections и понятная политика, что будет при пике (очередь в приложении, а не лавина коннектов).
  • Критичные запросы проверены через EXPLAIN: нет явных последовательных сканов там, где ожидается индекс.
  • Для списков и фильтров есть индексы под реальные WHERE и ORDER BY, а пагинация выбрана заранее (keyset там, где рост данных быстрый).
  • JSON-ответы не раздуты: возвращаете только нужные поля, без тяжелых вложений "на всякий случай".

Дальше важно автоматизировать то, что люди чаще всего забывают. Например, держите пару эталонных шаблонов запросов (поиск, список, детальная карточка), и договоритесь об одном формате пагинации для всех коллекций. Полезная привычка - включить логирование медленных запросов и собирать их в отдельный список для еженедельного разбора.

Чтобы не спорить на каждом PR, закрепите правила для новых эндпоинтов и код-ревью. Подойдет простой набор:

  • Для каждого списка обязателен лимит и стабильная сортировка.
  • Любой новый фильтр требует проверки индекса или аргумента, почему он не нужен.
  • В каждом хендлере есть таймаут и понятная обработка отмены запроса.
  • Нельзя добавлять поля в JSON без оценки размера и стоимости сборки.
  • Для изменений SQL есть "контрольный" EXPLAIN до и после.

Если вы собираете API через TakProsto, используйте planning mode, чтобы заранее описать списки, фильтры и формат ответов. Перед изменениями делайте снимок проекта, чтобы можно было быстро откатиться, если новый запрос неожиданно стал дорогим. А когда логика устоялась, экспортируйте код и прогоните финальную проверку под нагрузкой уже на вашей инфраструктуре и с вашими настройками Postgres.

Содержание
Какие тормоза обычно появляются у новых APIБыстрые проверки перед первыми реальными пользователямиПул соединений в Go: настройка без догадокЛимиты и защита Postgres от перегруза соединениямиПланы запросов: как читать EXPLAIN и что менятьИндексы для API: простые правила, которые работаютПагинация без сюрпризов: OFFSET vs keysetJSON-ответы: меньше работы и меньше байтЧастые ошибки и ловушки при тюнинге Go + PostgresПример: список сущностей в API до и после оптимизацииСледующие шаги: закрепить настройки и не откатиться назад
Поделиться
ТакПросто.ai
Создайте свое приложение с ТакПросто сегодня!

Лучший способ понять возможности ТакПросто — попробовать самому.

Начать бесплатноЗаказать демо