Якщо виклик Durable Object завершувався мережевим збоєм, розробникові раніше часто доводилося вирішувати, чи надсилати його ще раз. Із 5 листопада 2026 року частину таких повторів виконує runtime Cloudflare: він автоматично повторює певні невдалі виклики fetch() і RPC через stub. Для прикладного коду ключове питання тепер точніше: чи може конкретний метод безпечно виконатися вдруге?
Відповідь залежить від того, де перервався зв’язок. Runtime автоматично повторює деякі виклики, зберігаючи типово захист від подвійного виконання. За невизначеної доставки він використовує той самий ідентифікатор запиту, а об’єкт відхиляє повтор, якщо вже отримав першу спробу. Явно позначений метод retryable() поводиться інакше: він може запуститися знову, навіть якщо перша спроба вже дійшла до об’єкта. Тому позначка підходить лише для операцій, повтор яких безпечний і для стану, і для побічних ефектів.
Що саме повторює runtime
Згідно з оголошенням Cloudflare від 5 листопада, повтори поширюються на виклики fetch() і RPC до Durable Object, зроблені Worker або іншим Durable Object. Для викликів через stub типово передбачено першу спробу та до чотирьох повторів; нові спроби не починаються пізніше ніж через 10 секунд після старту виклику.

Умова — помилка з ознакою .retryable. Наприклад, запит міг не дійти до об’єкта, бо той перезапускався або переміщувався. Runtime також може повторити спробу, якщо з’єднання обірвалося і неможливо визначити, чи встиг об’єкт прийняти запит. Якщо об’єкт уже отримав запит, повтор із тим самим ідентифікатором відхиляється. Runtime не повторює помилки, викинуті кодом Durable Object, помилки з .overloaded і HTTP-відповіді на кшталт 500: це відповідь обробника, а не помилка доставки.
Чому повторна доставка — не те саме, що повтор операції
Повторне передавання запиту саме собою не означає повторного запуску методу. За невизначеного результату runtime надсилає запит із тим самим ідентифікатором; якщо об’єкт прийняв початкову спробу, він відхиляє повтор. Це запобігає повторному виконанню методу у звичайному режимі, наприклад повторному списанню коштів або створенню запису через один мережевий збій.

Межа змінюється, коли метод позначено через retryable() з cloudflare:durable-objects. Тоді об’єкту дозволено повторно виконати метод, якщо перша спроба вже могла початися. Cloudflare наводить два приклади: присвоїти товару задану кількість — ідемпотентно; збільшити кількість на одиницю — ні. Повтор першої дії встановлює те саме значення, а повтор другої додає ще одну одиницю.
Перевіряти потрібно не лише кінцевий стан сховища, а й усі ефекти методу. Якщо повтор створює ще один платіж, надсилає повідомлення або запускає зовнішню дію, однаковий стан усередині Durable Object не робить повтор безпечним. Позначка підходить, коли повтор не змінює сенсу результату й не дублює побічних ефектів.
Де корисна явна ідемпотентність
Встановлення значення, запис знімка стану або оновлення поля до відомого значення часто дають однаковий результат у разі повтору. Для таких методів retryable() може дозволити виклику завершитися успішно після обриву зв’язку, що стався вже після початку обробки.
Операції «додати», «створити ще одну», «списати» й «надіслати» зазвичай потребують іншого захисту. Перш ніж дозволити повторний запуск, переконайтеся, що бізнес-операція розпізнає дублікати або влаштована так, що повтор не створює другого ефекту. Сама назва функції нічого не гарантує: перевіряйте всі зміни стану й зовнішні дії всередині методу.
У retryable() вузька роль: він дозволяє повтор виконання, коли неможливо визначити, чи дійшов перший виклик. Він не змінює перелік помилок, на які реагує runtime, і не збільшує кількість спроб. Прапорець стосується функції; перевизначена або обгорнута версія методу не успадковує його автоматично, якщо її теж явно не позначити.
Що перевірити в уже працюючому проєкті
Найімовірніше, переглянути варто власні цикли повторів навколо викликів Durable Objects. Тепер кожна така спроба може включати повтори runtime, тому загальна кількість звернень буде більшою, ніж передбачає лише застосунок. Cloudflare радить скоротити власну кількість спроб або задати maxRetries: 0 для stub, якщо повторами керує ваш код.
Для конкретного stub ліміти задаються під час виклику get() або getByName(). Параметр maxRetries задає від нуля до десяти повторів після першої спроби; timeoutMs — інтервал, після якого нові спроби вже не стартують, від 500 до 60 000 мілісекунд. Ці налаштування застосовуються до викликів через цей stub. Можливості retryable() та об’єкт retry потребують Wrangler 4.158.0 або новішої версії.
Корисний перегляд складається з трьох запитань щодо кожного виклику: чи може він змінити стан більше ніж один раз; чи повторить він зовнішні побічні ефекти; чи має застосунок власну політику повторів. Потім вирішіть, чи повинен цей stub використовувати типові значення, чи власні ліміти. Для ідемпотентних методів можна окремо оцінити явну позначку; для решти залиште захист і перевірте обробку помилки, коли результат першої спроби невідомий.
Наслідок: відповідальність переміщується до межі методу
Автоматичний повтор прибирає частину мережевої логіки з прикладного коду, однак рішення про допустимість повторного виконання залишається властивістю операції. Runtime може безпечно повторити передавання й зупинитися, якщо не знає, чи виконався виклик. Розробник може дозволити повтор методу, явно підтвердивши, що він не дублює зміни стану або побічні ефекти.
Тому оновлення варто розглядати як зміну контракту між транспортним рівнем і обробником. Спершу перевірте власні цикли повторів і повторюваність побічних ефектів; потім налаштуйте ліміти для потрібних stubs. Так вбудована стійкість до короткочасних збоїв поєднується з контролем над операціями, де другий запуск має реальну ціну.