П'ять критичних помилок інтеграції API при запуску
Помилка № 1. Немає ідемпотентності і «шторм» ретраїв
Симптоми: дублі замовлень/платежів, розбіжність сум, спірні повернення, алерти DLQ зростають.
Корінь: повторна доставка запитів/вебхуків і мережеві флаппі - нормальні. Якщо операція «створити/списати» не ідемпотентна, ретраї множать збиток.
Як правильно
Idempotency-Key/' operation _ id'на всі небезпечні методи (POST/PATCH).
Унікальний індекс в БД по'operation _ id'. Повтор - поверніть минулий результат.
Вебхукі через Inbox-таблицю (dedupe по'event _ id + signature'). Вихідні події - Outbox.
Ретраї: максимум 1-2 рази, експонента + джиттер, тільки для безпечних операцій.
HTTP-конвенція (приклад):http
POST /v1/payments
Idempotency-Key: ik_f35a2
Content-Type: application/json
{"amount": 5000, "currency": "EUR", "source": "card_..."}
SQL-захист (спрощено):
sql
ALTER TABLE payments ADD CONSTRAINT uniq_op UNIQUE (operation_id);
Ретраї з джиттером (псевдокод):
python for i in range(2):
try: return call_api(payload, timeout=0. 6)
except Timeout:
sleep(0. 05 2i + random. uniform(0, 0. 05))
raise UpstreamUnavailable
Чек-лист:
- Вся «грошова/створююча» логіка має'operation _ id'і uniq-індекс.
- Вхідні вебхуки тільки через Inbox з ідемпотентним воркером.
- Клієнтська SDK автоматично проставляє Idempotency-Key.
Помилка № 2. Тайм-аути/ретраї проти SLO: «перегрів» залежностей
Симптоми: p95 раптово спливає, черги ростуть, circuit breaker «човкає».
Корінь: загальний SLO відповіді - 400-600 мс, а тайм-аути до зовнішніх API - по 1-2 с, та ще ретраї × 3. Ви робите довше, ніж можете, і штурмуєте залежність повторами.
Як правильно
Budget-таймінг: якщо SLO 400 мс, upstream-тайм-аут: 250-300 мс; загальний тайм-аут запиту ≤ SLO.
Limits/Backpressure: семафори/worker-pool на виклики до кожної залежності. Переповнено → 429/503 відразу.
Circuit breaker: «open» при тайм-аутах/5хх, «half-open» дозовано.
Admission control: обмежте паралелізм (на потік, на endpoint/PSP).
Приклад (Go):go sem:= make (chan struct {}, 64 )//ліміт конкуренції до PSP func callPSP (ctx context. Context, req Req) (Res, error) {
select {
case sem <- struct{}{}:
defer func(){ <-sem }()
c, cancel:= context. WithTimeout(ctx, 300time. Millisecond)
defer cancel()
return psp. Do(c, req)
default:
return Res {}, ErrBusy//негайна відмова замість черги без кінця
}
}
Чек-лист:
- Тайм-аути коротше SLO; ретраї ≤ 2; є джиттер.
- Пули/семафори на зовнішні API; circuit breaker з метриками.
- На «busy» маршрутах повертаємо 429/Retry-After, а не тримаємо з'єднання.
Помилка № 3. Слабка безпека: підписи вебхуків, секрети, TLS
Симптоми: «чужі» вебхуки проходять, секрети в коді/лозі, MITM-ризики.
Корінь: немає перевірки підпису/свіжості, секрети живуть в env-файлах, старі TLS і слабкі заголовки.
Як правильно
Підпис вебхуків HMAC-SHA256 +'X-Timestamp'( вікно ≤ 5-10 хв), суворе порівняння підпису.
mTLS для критичних інтеграцій або IP allow-list.
Ротація секретів через Vault/Cloud KMS; мінімум прав; аудит вичитки.
TLS 1. 2/1. 3 only, HSTS, правильні CORS (вузький список джерел).
Перевірка підпису (Python):python def verify(sig_hdr, ts_hdr, body, secret):
if abs(time. time() - int(ts_hdr)) > 600: raise Expired()
calc = hmac. new(secret, (ts_hdr + "." + body). encode(), hashlib. sha256). hexdigest()
if not hmac. compare_digest(calc, sig_hdr): raise BadSig()
Чек-лист:
- Всі вебхуки підписані і перевіряються; вікно свіжості обмежене.
- Секрети в KMS/Vault, є ротація і аудит.
- TLS/HSTS включені; CORS точковий; IP/mTLS де доречно.
Помилка № 4. Контракт-дрифт: схема «жила своїм життям»
Симптоми: прод падав «тільки у частини клієнтів», 500/422 в логах, різні версії SDK і API сперечаються.
Корінь: немає суворого опису контрактів, назад несумісні зміни, «тихі» поля, різний сенс у однакових назв.
Як правильно
Контракт-перший: OpenAPI/AsyncAPI + генерація серверів/клієнтів; для подій - Avro/Protobuf + Schema Registry.
Версіонування: 'v1 → v2'( URI/хедер), deprecation-план, grace-період.
Backward-compat: тільки additive зміни в мінорних релізах; заборона видаляти/перейменовувати без v-bump.
Контрактні тести: Pact/Buf - провайдер/консумер перевіряються в CI.
Приклади:yaml
OpenAPI: чіткий тип суми в мінорних одиницях amount_minor:
type: integer minimum: 0 description: Сума в мінімальних одиницях валюти (ціле)
Чек-лист:
- Контракти зберігаються в git, CI валідує/ламає при несумісності.
- Регістри схем для подій, сумісність «back/forward».
- Док-сторінка змін, дати деприкації, тестовий стенд для партнерів.
Помилка № 5. «Сліпий» запуск: немає метрик/логів/трейсів і пісочниці
Симптоми: «нічого не видно», підтримку завалює, дебаг - руками в проді.
Корінь: не включили спостережуваність, немає синтетики, пісочницю тестили «на словах».
Як правильно
RED/USE-метрики: rate/error/latency на кожному endpoint, за маршрутами/методами.
Кореляція: 'trace _ id'у всіх логах і відповідях; зв'язування zapros↔vebkhuk.
Синтетика: health-проби (login/deposit-пісок), SLA-моніторинг T + 60 для вебхуків.
Пісочниця/стейдж: повністю ізольовані ключі/домени, фіктивні PSP, записи «не потрапляють у звіти».
Відповідь з trace-ідентифікатором:http
HTTP/1. 1 202 Accepted
Trace-Id: 7f2b3d8e9c1a4
Location: /v1/ops/req_42/status
Чек-лист:
- Метрики RED/USE, дашборди, алерти (симптоми + причини).
- Трейси end-to-end; логи JSON, без PII, з'trace _ id'.
- Синтетика з ключових регіонів; пісочниця обов'язкова, ключі різні.
Прелаунч-план (T-7 → T-0)
T-7 днів:- Фінальний контракт-скан: чи немає несумісних змін; freeze схем.
- Секрети/сертифікати: перевірте ротацію, доступи, KMS-політики.
- Синтетика 24 × 7, алерти прив'язані до on-call.
- Навантажувальний міні-прогін (burst 2-5 хв): р95/пули/черги в зеленій зоні.
- DRY-RUN вебхуків (повтори, 5xx, джиттер), перевірка DLQ.
- «Книга телефонів» партнерів: L1/L2 контакти, war-room канал.
- Канарний трафік 5% → 25% → 50% по SLO-гейтам; готовий rollback.
- Включені kill-switch/feature-flags на ризикових фічах.
- War-room активний, статус-шаблони підготовлені.
Роллбек-план (якщо щось пішло не так)
1. Зняти трафік на попередню стабільну версію/маршрут.
2. Відключити фічефлагом спірні зміни.
3. Стабілізувати черги/пули, зупинити ретраї при «штормі».
4. Пост-інцидент: зібрати таймлайн, коріння, завдання (фікс-форвард/фікси контракту).
Таблиця самоперевірки на запуск (коротка)
Часто задаються «а як бути, якщо...»
... провайдер не підтримує Idempotency-Key?
Зберігайте'hash (body)'+'partner _ request _ id'і вводьте свою ідемпотентність.
... вебхуки іноді приходять «раніше» відповіді?
Зшивайте по'operation _ id'і тимчасово тримайте «unknown → reconcile» статус; періодичний reconciler закриє розбіжності.
Треба підтримати старих клієнтів і нових?
Версіонуйте endpoint'и ('/v1'і '/v2'), маршрутизуйте по заголовку/URI, тримайте backward-сумісність мінімум N місяців.
Резюме
Провали інтеграцій майже завжди про одне і те ж: немає ідемпотентності, неправильні тайм-аути і ретраї, слабкий підпис вебхуків, дрейф контрактів і відсутність видимості. Заздалегідь зафіксуйте контракти, увімкніть спостережуваність, розставте ліміти/бекпрешер, підпишіть всі зовнішні взаємодії і запустіть синтетику. Тоді навіть при збоях у партнерів ваш реліз залишиться керованим - без грошей, втрачених в ретраях, і без безсонної ночі у всієї команди.