This media is not supported in your browser
VIEW IN TELEGRAM
Хочешь избежать проблем, когда Cloudflare падает?
Или когда La Liga блокирует твои страницы?
Разработчик сделал open-source CLI, чтобы можно было легко отключать этот сервис в проектах за пару секунд.
👉 @BackendPortal
Или когда La Liga блокирует твои страницы?
Разработчик сделал open-source CLI, чтобы можно было легко отключать этот сервис в проектах за пару секунд.
$ npx disable-cloudflare@latest
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9
12 рекомендаций по дизайну API для бэкенд-разработчиков
(Их часто спрашивают на собеседованиях)
1. Понятные имена ресурсов
2. Корректное использование HTTP-методов
-
-
-
-
3. Идемпотентность
Клиент отправляет:
Если запрос повторится, сервер должен вернуть тот же результат, не создавая операцию заново.
4. Версионирование API
Рекомендуемый вариант — в URL:
5. Правильные статус-коды
Если пользователь не найден:
6. Пагинация
Пример:
Ответ должен содержать элементы 51–100.
7. Фильтрация и сортировка
Пример:
8. Безопасность
Использование JWT в заголовках:
9. Rate limiting
Например: 100 запросов в минуту.
После превышения — вернуть:
10. Кэширование
Запрос:
Ответ содержит:
Повторный запрос:
Если не изменилось — 304 Not Modified.
11. Документация
Используй:
- Swagger UI
- OpenAPI
Разработчики должны видеть схемы, параметры и иметь возможность тестировать запросы.
12. Быть прагматичным
Иногда лучше так:
чем строго REST-подход:
Хороший API читается как логичная, предсказуемая система и экономит время всем, кто с ним работает.
👉 @BackendPortal
(Их часто спрашивают на собеседованиях)
1. Понятные имена ресурсов
❌`GET /get-all-orders`
✅`GET /orders`
2. Корректное использование HTTP-методов
-
POST /users — создать пользователя -
GET /users/123 — получить пользователя -
PUT /users/123 — заменить полностью -
DELETE /users/123 — удалить 3. Идемпотентность
Клиент отправляет:
POST /payments
Idempotency-Key: abc-123
Если запрос повторится, сервер должен вернуть тот же результат, не создавая операцию заново.
4. Версионирование API
Рекомендуемый вариант — в URL:
GET /v1/products/42
GET /v2/products/42
5. Правильные статус-коды
Если пользователь не найден:
❌ `200 OK { "error": "user not found" }`
✅ `404 Not Found`6. Пагинация
Пример:
GET /articles?page=2&limit=50
Ответ должен содержать элементы 51–100.
7. Фильтрация и сортировка
Пример:
GET /orders?status=shipped&sort=-created_at
8. Безопасность
Использование JWT в заголовках:
Authorization: Bearer <token>
9. Rate limiting
Например: 100 запросов в минуту.
После превышения — вернуть:
429 Too Many Requests
10. Кэширование
Запрос:
GET /blog/posts/123
Ответ содержит:
ETag: "abc"
Повторный запрос:
If-None-Match: "abc"
Если не изменилось — 304 Not Modified.
11. Документация
Используй:
- Swagger UI
- OpenAPI
Разработчики должны видеть схемы, параметры и иметь возможность тестировать запросы.
12. Быть прагматичным
Иногда лучше так:
POST /auth/login
чем строго REST-подход:
POST /sessions
Хороший API читается как логичная, предсказуемая система и экономит время всем, кто с ним работает.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12🔥6
С UUIDv7 в PostgreSQL 18 сортировка через ORDER BY теперь реально выдаёт записи в порядке их создания.
👉 @BackendPortal
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14❤4👍2
Proxmox 9.1 теперь нативно поддерживает OCI-образы (Docker)
Proxmox VE 9.1 теперь поддерживает OCI-контейнеры на базе LXC, использует ядро Linux 6.17 и содержит улучшения в области виртуализации, безопасности и сетевых функций
Подробнее здесь
👉 @BackendPortal
Proxmox VE 9.1 теперь поддерживает OCI-контейнеры на базе LXC, использует ядро Linux 6.17 и содержит улучшения в области виртуализации, безопасности и сетевых функций
Подробнее здесь
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤3🔥3
Media is too big
VIEW IN TELEGRAM
Ты правильно используешь Docker.?
Вот две вещи, которые СКОРЕЕ ВСЕГО ты упускаешь:
• У тебя Dockerfile в один stage. Это медленно.
• Ты почти не используешь кэширование слоев. Это тоже медленно.
Уже несколько лет Docker по умолчанию использует BuildKit как основной движок, и он поддерживает multi-stage Dockerfile.
Суть такая:
Обычный single-stage Dockerfile (скорее всего, у тебя как раз такой) заставляет каждый шаг зависеть от предыдущего.
Это значит:
• Все шаги выполняются строго последовательно
• Итоговый образ раздувается
• Любое изменение ломает кэш следующих слоев
• Нет шансов что-то реально распараллелить
Меняешь одну строку в начале Dockerfile = все слои после нее идут мимо кэша.
Есть вариант получше:
Начни использовать multi-stage сборки.
Парень записал видео, где сравниваю медленную single-stage сборку и быструю multi-stage.
Что нужно сделать:
Разбей Dockerfile на независимые стадии с помощью нескольких FROM. BuildKit построит граф зависимостей и будет гонять независимые стадии параллельно.
Плюсы тут такие:
Сборка станет намного быстрее. Параллельные стадии реально экономят кучу времени.
Кэширование будет намного эффективнее. У каждого stage свой набор слоев. Если что-то изменилось в build-стейдже, финальный stage не инвалидируется.
Итоговый образ будет чистым. Тебе не нужно тянуть туда тулчейн, компиляторы и временные файлы. В финальный образ копируется только то, что реально нужно.
Для меня это стало огромным апгрейдом того, как я пишу Dockerfile.
👉 @BackendPortal
Вот две вещи, которые СКОРЕЕ ВСЕГО ты упускаешь:
• У тебя Dockerfile в один stage. Это медленно.
• Ты почти не используешь кэширование слоев. Это тоже медленно.
Уже несколько лет Docker по умолчанию использует BuildKit как основной движок, и он поддерживает multi-stage Dockerfile.
Суть такая:
Обычный single-stage Dockerfile (скорее всего, у тебя как раз такой) заставляет каждый шаг зависеть от предыдущего.
Это значит:
• Все шаги выполняются строго последовательно
• Итоговый образ раздувается
• Любое изменение ломает кэш следующих слоев
• Нет шансов что-то реально распараллелить
Меняешь одну строку в начале Dockerfile = все слои после нее идут мимо кэша.
Есть вариант получше:
Начни использовать multi-stage сборки.
Парень записал видео, где сравниваю медленную single-stage сборку и быструю multi-stage.
Что нужно сделать:
Разбей Dockerfile на независимые стадии с помощью нескольких FROM. BuildKit построит граф зависимостей и будет гонять независимые стадии параллельно.
Плюсы тут такие:
Сборка станет намного быстрее. Параллельные стадии реально экономят кучу времени.
Кэширование будет намного эффективнее. У каждого stage свой набор слоев. Если что-то изменилось в build-стейдже, финальный stage не инвалидируется.
Итоговый образ будет чистым. Тебе не нужно тянуть туда тулчейн, компиляторы и временные файлы. В финальный образ копируется только то, что реально нужно.
Для меня это стало огромным апгрейдом того, как я пишу Dockerfile.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4
This media is not supported in your browser
VIEW IN TELEGRAM
Небольшая новость для тех, кто работает с PostgreSQL.
У Postgres есть официальное расширение для VS Code. Можно работать с базой прямо в редакторе без лишних тулз и переключений.
Что внутри:
- Визуализация схемы
- Поддержка агентов для взаимодействия с базой
- Метрики, аналитика и мониторинг
- Быстрый запуск PostgreSQL в Docker, если нужно локальное окружение
- Умный IntelliSense с учётом контекста базы: автодополнение, форматирование, подсветка синтаксиса
И это только основные фишки.
Кому интересно, вот расширение: тык
👉 @BackendPortal
У Postgres есть официальное расширение для VS Code. Можно работать с базой прямо в редакторе без лишних тулз и переключений.
Что внутри:
- Визуализация схемы
- Поддержка агентов для взаимодействия с базой
- Метрики, аналитика и мониторинг
- Быстрый запуск PostgreSQL в Docker, если нужно локальное окружение
- Умный IntelliSense с учётом контекста базы: автодополнение, форматирование, подсветка синтаксиса
И это только основные фишки.
Кому интересно, вот расширение: тык
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18❤6
Почему JSON жрет твой CPU
Твой API тупит. Ты думаешь что база медленная, сеть лагает. Но реальная пробка может быть в том формате, на котором всё общается.
JSON это не формат данных. Это текст.
Каждый раз, когда ты отправляешь {"id": 12345}, сервер платит скрытый "налог на парсинг". Даже самые быстрые парсеры вроде simdjson упираются в аппаратные ограничения, которых у бинарных форматов просто нет.
Разложим по технике.
1. Цена на CPU (state-machine против арифметики)
JSON (текст):
Чтобы прочитать число 12345, CPU получает сырые байты. Даже оптимизированный парсер должен пройти через state machine:
- искать структурные символы (: , { }).
- проверять escape-последовательности.
- а потом конвертировать строку в число:
цикл: взять char, вычесть '0', умножить накопленное на 10, прибавить.
Это прыжки в ветках, пропуски кеша, ситуации, где CPU просто ждет.
Protobuf (бинарный):
Отправляет Varint (для маленьких чисел) или фиксированный формат.
fixed32 => просто memcpy. Никакого парсинга.
Varint => читаешь байт, смотришь флаг в старшем бите (MSB), решаешь, идет ли число дальше.
Результат: несколько битовых операций. На нагрузках с большим количеством чисел бинарный формат фундаментально быстрее.
2. Стоимость по сети (энтропия против повторов)
JSON:
Ты передаешь ключ "status" снова и снова.
Контраргумент:
Ответ:
Тебе нужно:
Serialize JSON → Compress → Send
и у получателя наоборот: Receive → Decompress → Parse JSON.
Ты сжимаешь текст, который вообще не должен повторяться.
Protobuf:
Схема отдельно, данные отдельно. На проводе вместо "status" просто ID поля. [Tag: 1][Value: "active"]. Сжатие уже почти ненужно —> полезной нагрузки меньше.
3. Цена надежности (Schema-on-Read)
JSON это "схема при чтении". Ты получаешь кусок текста и надеешься, что id правда число. В итоге:
if (typeof id !== 'number') ...
или тащишь валидатор вроде Zod/Pydantic, что снова жрет CPU.
Protobuf — "схема при записи".
Контракт жесткий = типы известны заранее, и на границе сериализации ты получаешь гарантии. Валидация есть, но намного дешевле.
JSON удобен для публичных API, потому что читаемый и дружелюбный.
Но в высоконагруженных микросервисах JSON это налог. Ты тратишь железо, чтобы каждый раз разбирать текст.
gRPC/Protobuf это не сверхчудо. Ты просто переносишь сложность с рантайма (парсинг текста) в билд-стадию (генерация кода).
И CPU говорит спасибо.🥰
👉 @BackendPortal
Твой API тупит. Ты думаешь что база медленная, сеть лагает. Но реальная пробка может быть в том формате, на котором всё общается.
JSON это не формат данных. Это текст.
Каждый раз, когда ты отправляешь {"id": 12345}, сервер платит скрытый "налог на парсинг". Даже самые быстрые парсеры вроде simdjson упираются в аппаратные ограничения, которых у бинарных форматов просто нет.
Разложим по технике.
1. Цена на CPU (state-machine против арифметики)
JSON (текст):
Чтобы прочитать число 12345, CPU получает сырые байты. Даже оптимизированный парсер должен пройти через state machine:
- искать структурные символы (: , { }).
- проверять escape-последовательности.
- а потом конвертировать строку в число:
цикл: взять char, вычесть '0', умножить накопленное на 10, прибавить.
Это прыжки в ветках, пропуски кеша, ситуации, где CPU просто ждет.
Protobuf (бинарный):
Отправляет Varint (для маленьких чисел) или фиксированный формат.
fixed32 => просто memcpy. Никакого парсинга.
Varint => читаешь байт, смотришь флаг в старшем бите (MSB), решаешь, идет ли число дальше.
Результат: несколько битовых операций. На нагрузках с большим количеством чисел бинарный формат фундаментально быстрее.
2. Стоимость по сети (энтропия против повторов)
JSON:
[
{"status": "active"},
{"status": "active"}
]
Ты передаешь ключ "status" снова и снова.
Контраргумент:
gzip всё решит!
Ответ:
gzip решает сеть, но ест CPU.
Тебе нужно:
Serialize JSON → Compress → Send
и у получателя наоборот: Receive → Decompress → Parse JSON.
Ты сжимаешь текст, который вообще не должен повторяться.
Protobuf:
Схема отдельно, данные отдельно. На проводе вместо "status" просто ID поля. [Tag: 1][Value: "active"]. Сжатие уже почти ненужно —> полезной нагрузки меньше.
3. Цена надежности (Schema-on-Read)
JSON это "схема при чтении". Ты получаешь кусок текста и надеешься, что id правда число. В итоге:
if (typeof id !== 'number') ...
или тащишь валидатор вроде Zod/Pydantic, что снова жрет CPU.
Protobuf — "схема при записи".
Контракт жесткий = типы известны заранее, и на границе сериализации ты получаешь гарантии. Валидация есть, но намного дешевле.
JSON удобен для публичных API, потому что читаемый и дружелюбный.
Но в высоконагруженных микросервисах JSON это налог. Ты тратишь железо, чтобы каждый раз разбирать текст.
gRPC/Protobuf это не сверхчудо. Ты просто переносишь сложность с рантайма (парсинг текста) в билд-стадию (генерация кода).
И CPU говорит спасибо.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍4😁2🤔2🔥1
Сообщество разработчиков объявило о выходе экспериментального CRDT-расширения для Postgres. Проект открыт и доступен для изучения и использования.
CRDT это тип данных, который применяется в приложениях с одновременным редактированием. Простой пример — Google Docs, где несколько пользователей могут печатать одновременно, а изменения автоматически объединяются без конфликтов.
Обычно такие структуры сериализуются на стороне сервера и только потом сохраняются в базу. Новое расширение меняет подход: теперь Postgres может работать с CRDT нативно — хранить, индексировать, искать и автоматически объединять изменения прямо в базе данных.
Авторы проекта показывают, как это может выглядеть в будущем:
Идея в том, чтобы отправлять только diff изменений, а база уже сама разрулит конфликты, вместо того чтобы перезаписывать данные.
Также предполагается поддержка WebSockets для быстрого обмена изменениями между клиентами и последующей отправки батчей в Postgres.
Проект может стать важным шагом для приложений реального времени, совместного редактирования контента и распределённых систем.
👉 @BackendPortal
CRDT это тип данных, который применяется в приложениях с одновременным редактированием. Простой пример — Google Docs, где несколько пользователей могут печатать одновременно, а изменения автоматически объединяются без конфликтов.
Обычно такие структуры сериализуются на стороне сервера и только потом сохраняются в базу. Новое расширение меняет подход: теперь Postgres может работать с CRDT нативно — хранить, индексировать, искать и автоматически объединять изменения прямо в базе данных.
Авторы проекта показывают, как это может выглядеть в будущем:
create table blog_posts (
id uuid primary key,
title text,
body crdt default '{}'
);
Идея в том, чтобы отправлять только diff изменений, а база уже сама разрулит конфликты, вместо того чтобы перезаписывать данные.
Также предполагается поддержка WebSockets для быстрого обмена изменениями между клиентами и последующей отправки батчей в Postgres.
Проект может стать важным шагом для приложений реального времени, совместного редактирования контента и распределённых систем.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13🤔3
Совет: всегда добавляй workflow_dispatch в триггеры workflow.
Так у тебя появится кнопка в UI GitHub, чтобы вручную запускать новые прогонки (когда CI, как обычно, развалится).
👉 @BackendPortal
Так у тебя появится кнопка в UI GitHub, чтобы вручную запускать новые прогонки (когда CI, как обычно, развалится).
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8🔥1
Еще одна книжка на полку. Пятое издание. Подборка статей, собранных Стоунбрейкером, Питером Бейлисом и Джозефом Хеллерстейном. PDF доступен бесплатно.
redbook.io/pdf/redbook-5th-edition.pdf
👉 @BackendPortal
redbook.io/pdf/redbook-5th-edition.pdf
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Пиковый опыт разработки на TypeScript в бэкенде.
Определяешь маршрут, возвращаешь данные, всё полностью типобезопасно.
Типобезопасность тянется до фронтенда через RPC-подобный коннектор.
Документация по API генерируется для всех ответов.
OpenTelemetry заводится меньше чем за 10 строк.
Живём в интересное время.
Код тоже очень хороший, чувак написал его примерно за час.
https://github.com/SaltyAom/elysia-prisma-better-auth-example
👉 @BackendPortal
Определяешь маршрут, возвращаешь данные, всё полностью типобезопасно.
Типобезопасность тянется до фронтенда через RPC-подобный коннектор.
Документация по API генерируется для всех ответов.
OpenTelemetry заводится меньше чем за 10 строк.
Живём в интересное время.
Код тоже очень хороший, чувак написал его примерно за час.
https://github.com/SaltyAom/elysia-prisma-better-auth-example
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍2🔥2
Одна простая привычка, которая сильно упрощает поддержку Dockerfile, это сортировка многострочных списков пакетов по алфавиту.
На первый взгляд мелочь, но влияние на читаемость и будущую поддержку заметное.
Когда ставишь пакеты в многострочном apt-get install или apk add блоке, легко случайно добавить дубликат или пропустить что-то, что затерялось в середине списка.
Алфавитная сортировка полностью снимает этот вопрос. Список можно быстро просканировать, сразу увидеть дубли и держать всё в едином стиле на разных окружениях.
Плюс уменьшаются шумные диффы в код-ревью.
Когда пакеты отсортированы, добавление или удаление одного пункта выглядит как аккуратное и предсказуемое изменение.
Без сортировки маленькое обновление часто превращается в огромный diff, и ревью становится сложнее, чем должно быть.
Этот подход особенно полезен, когда команда растёт.
Несколько человек, трогающих один Dockerfile, не начинают перетасовывать строки под свой вкус или форматировать по-разному.
Структура остаётся стабильной, и поддержка со временем становится проще.
Небольшое улучшение, но на сотнях билдов оно экономит заметно нервов и времени.
👉 @BackendPortal
На первый взгляд мелочь, но влияние на читаемость и будущую поддержку заметное.
Когда ставишь пакеты в многострочном apt-get install или apk add блоке, легко случайно добавить дубликат или пропустить что-то, что затерялось в середине списка.
Алфавитная сортировка полностью снимает этот вопрос. Список можно быстро просканировать, сразу увидеть дубли и держать всё в едином стиле на разных окружениях.
Плюс уменьшаются шумные диффы в код-ревью.
Когда пакеты отсортированы, добавление или удаление одного пункта выглядит как аккуратное и предсказуемое изменение.
Без сортировки маленькое обновление часто превращается в огромный diff, и ревью становится сложнее, чем должно быть.
Этот подход особенно полезен, когда команда растёт.
Несколько человек, трогающих один Dockerfile, не начинают перетасовывать строки под свой вкус или форматировать по-разному.
Структура остаётся стабильной, и поддержка со временем становится проще.
Небольшое улучшение, но на сотнях билдов оно экономит заметно нервов и времени.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤4
This media is not supported in your browser
VIEW IN TELEGRAM
AWS открыл бесплатный доступ к SimuLearn до 6 января!
✓ Реальные симуляции, чтобы прокачать навыки по облакам
✓ Без кредитки и без риска внезапных списаний
✓ EC2, NoSQL, архитектура, траффик под нагрузкой и другое
Один из топовых ресурсов:
→ ссылка
👉 @BackendPortal
✓ Реальные симуляции, чтобы прокачать навыки по облакам
✓ Без кредитки и без риска внезапных списаний
✓ EC2, NoSQL, архитектура, траффик под нагрузкой и другое
Один из топовых ресурсов:
→ ссылка
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6
Короткая заметка про k8s:
Оказалось, что можно настраивать лимиты пропускной способности для пода или деплоймента. По умолчанию эта фича отключена. Но входящий и исходящий трафик можно контролировать через аннотации на поде, примерно так 😃
Кстати: M это Mbps, G это Gbps.
👉 @BackendPortal
Оказалось, что можно настраивать лимиты пропускной способности для пода или деплоймента. По умолчанию эта фича отключена. Но входящий и исходящий трафик можно контролировать через аннотации на поде, примерно так 😃
Кстати: M это Mbps, G это Gbps.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
This media is not supported in your browser
VIEW IN TELEGRAM
Сегодня решаю классическую задачу из распределенных систем:
Неожиданно, но ни один популярный инструмент контейнеризации это нормально не делает.
docker service logs, kubectl logs, stern, kubetail, k9s — все они просто перемешивают стримы в порядке получения. Стандартный костыль — пропустить вывод через🙃
Чтобы сделать это правильно, просто печатать логи по мере поступления нельзя, потому что более медленный стрим может прислать запись с более ранней меткой времени. Нужно понимать момент, когда запись можно выводить безопасно.
Вот как я решаю это в новой команде uc logs. Требуется две вещи:
1. Low watermark
Отслеживаем минимальный timestamp среди всех стримов и безопасно выводим буферизованные логи, у которых timestamp ниже этого watermark.
2. Heartbeat timestamps
Что если контейнер просто замолчит? Тогда весь вывод зависнет, потому что watermark не будет сдвигаться.
Решение - периодически отправлять пустые heartbeat-записи с текущим timestamp на сервере. Это по сути обещание: "У меня нет логов, которые старше этого времени".
Это позволяет клиенту продвигать watermark без блокировки вывода. На практике интервал 500 мс – 1 сек работает нормально.
Что насчет несинхронизированных системных часов?
Тут особо ничего не сделаешь, не усложняя систему. Просто детектируем проблему, предупреждаем пользователя и живем дальше.
👉 @BackendPortal
как надежно стримить логи с нескольких реплик в хронологическом порядке?
Неожиданно, но ни один популярный инструмент контейнеризации это нормально не делает.
docker service logs, kubectl logs, stern, kubetail, k9s — все они просто перемешивают стримы в порядке получения. Стандартный костыль — пропустить вывод через
| sort Чтобы сделать это правильно, просто печатать логи по мере поступления нельзя, потому что более медленный стрим может прислать запись с более ранней меткой времени. Нужно понимать момент, когда запись можно выводить безопасно.
Вот как я решаю это в новой команде uc logs. Требуется две вещи:
1. Low watermark
Отслеживаем минимальный timestamp среди всех стримов и безопасно выводим буферизованные логи, у которых timestamp ниже этого watermark.
watermark = min(latest_timestamp for each stream)
sort and print all buffered logs where timestamp < watermark
2. Heartbeat timestamps
Что если контейнер просто замолчит? Тогда весь вывод зависнет, потому что watermark не будет сдвигаться.
Решение - периодически отправлять пустые heartbeat-записи с текущим timestamp на сервере. Это по сути обещание: "У меня нет логов, которые старше этого времени".
Это позволяет клиенту продвигать watermark без блокировки вывода. На практике интервал 500 мс – 1 сек работает нормально.
Что насчет несинхронизированных системных часов?
Тут особо ничего не сделаешь, не усложняя систему. Просто детектируем проблему, предупреждаем пользователя и живем дальше.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3