Міграція – це дві задачі на читання з будівництвом посередині

За два тижні ми перенесли всі автоматизації між Stripe і нашою CRM із Zapier на n8n, що працює на нашому власному сервері. Вісімнадцять Zap-ів стали одинадцятьма сценаріями. Будувати виявилося найдешевше: насправді ці два тижні пішли на те, щоб прочитати, що робили ці Zap-и, а тоді довести, що нові сценарії роблять те саме і правильно. Під час цього читання знайшлися 889 пар інвойсів-дублікатів, валюта, зашита в код як USD, і поле кількості, яке стояло порожнім від самого дня, коли його підключили.

Найзавантаженіший шлях, яким у компанії рухаються гроші, показував у шапці редактора 99 / 100 steps. Більше сотні кроків Zapier в один Zap не пускає. Ця автоматизація перетворює запис у нашій CRM на інвойс клієнтові в Stripe, три роки вона розросталася копіпастом, і запасу в неї лишився рівно один крок – далі будь-яка зміна вимагала б переписати все.

Два тижні ми переносили її і все довкола на n8n на власному сервері. Вісімнадцять Zap-ів стали одинадцятьма сценаріями. Працював я з Claude Code на Opus 5 у режимі підвищених зусиль, а ще – з уже відкритою сесією власника акаунта в його браузері, і несподіванкою для мене стало те, куди пішли ці два тижні.

Збудувати одинадцять сценаріїв було найдешевше. У n8n є повноцінний редактор, а агент, який до публікації звіряє граф вузлів з їхніми описами, робить роботу в ньому ще дешевшою. Дорога робота лежала по обидва боки від будівництва: прочитати, що насправді робили Zap-и, і довести, що заміни роблять те саме. Обидві задачі – про прозорість, і саме за прозорість у міграції й платиш.

Звідси рішення, яке доводиться ухвалювати разів вісімнадцять. Міграція змушує прочитати кожен рядок логіки автоматизацій, які ви весь цей час ганяли, не заглядаючи всередину, тож дефекти ви знайдете, і щодо кожного вирішуватимете: перенести як є чи виправити. У нас набралося дванадцять таких, що варто записати: валюта, зашита в код як USD на одній із гілок, що складають інвойс; кількість, яку брали з поля CRM, порожнього від самого дня підключення, тож Stripe щоразу мовчки отримував 1; і три Zap-и, які паралельно створювали записи інвойсів, нічого не знаючи один про одного, – через них в історії CRM лишилося 889 пар дублікатів.

Інвентаризація – це вимірювання, яке зсувається, поки ти міряєш

Порахуйте ту саму міграцію в чотирьох одиницях – і отримаєте чотири різні проєкти.

У Zap-ах: 140 в акаунті, з них важили 18. У кроках: ці вісімнадцять давали приблизно 300 панелей зіставлення полів, причому 99 із них – в одному Zap-і, а в більшості решти – менше п’ятнадцяти. У теках: вісім, одна з них названа іменем конкретної людини, і саме в ній лежить канал, яким фінвідділ позначає інвойси оплаченими. У тому, що прийшло на заміну: одинадцять сценаріїв n8n, найбільший – на 24 вузли, на сервері, де тепер працюють 34 живі сценарії і ще 39 лежать в архіві.

Помилився я в найпростішому числі. На фінішній прямій я був певен, що ввімкненими лишаються п’ять Zap-ів. П’ять показувала тека переді мною, і записаний у травні знімок стану з цим погоджувався – а саме за таких умов людина й перестає перевіряти. Правильне питання ставиться до списку всіх активів акаунта з фільтром за статусом On і знятим чипом «owner is me», який стоїть за замовчуванням, – і відповідь на нього: дев’ять. Два з цих дев’яти зробили під час міграції: колега розв’язував сьогоднішню проблему тим інструментом, який ще був під рукою.

[тодішній макс]

На той час акаунт майже простоював – 20 використаних задач із 10 000, дозволених на розрахунковий період, – і все одно тримав на собі частину ваги. Простоювати й водночас бути несучим – звичайний фінал для таких платформ, і саме тому залишок ніхто не помічає.

Найдорожчою знахідкою виявилося не число, а сам візерунок. У колеги, який звільнявся, закінчився строк дії підключення до пошти, і десять Zap-ів, що входили через нього, лишилися ввімкненими – і замовкли. Тригер, який не може перевірити пошту, нічого не запускає, а де немає запусків, немає й помилок, тож історія лишалася чистою, а кожен перемикач – зеленим. За нашими оцінками, близько 130 записів так і не дійшли до CRM за шість робочих днів, поки скарги нарешті не пов’язали з причиною.

[адвокат диявола]

Кроки існують тільки на екрані

Власний MCP-сервер Zapier відповідає на питання про Zap: як він називається, який у нього id, чи ввімкнений він, хто правив його останнім і коли його востаннє вмикали. Про кроки – ані слова. Я перевіряв двічі, з різницею в два місяці, – раптом я проґавив потрібну функцію. Жоден тариф, який ми знайшли, взагалі не продає зіставлення полів через API.

Тож розвилка була справжня, і до неї неминуче приходить кожен, хто йде із закритої платформи автоматизацій.

як прочитати 300 панелей із кроками на платформі, яка не дає їх експортувати вибір: керувати браузером із відкритою сесією
критерій MCP від постачальника дорожчий тариф знімки екрана вручну керувати браузером обрано
повертає зіставлення полів ні невідомо, чи є такий тариф узагалі так так
повертає умови фільтрів ні невідомо так так, через редактор чернетки
вартість жодної новий договір із платформою, з якої ми йдемо кілька днів роботи колеги жодної
ризик для живих автоматизацій жодного жодного жодного відкриває чернетку живого Zap-а
швидкість не стосується не стосується по панелі на кожне прохання, і чекай приблизно панель за хвилину

Купувати дорожчий тариф продукту, від якого ми збиралися відмовитися за три тижні, мені хотілося найменше, та ще й підтвердити, що це спрацює, я не міг. Тож браузером керував Claude Code. Спрацювало ось що: заходити через список тек, а не прямим посиланням на редактор, клацнути крок, щоб відкрити його панель, а тоді витягти текст панелі коротким скриптом, який чіпляється за знайому мітку й піднімається вгору до контейнера, де вона лежить. Я двічі звірив результат із панеллю, яку прочитав і на власні очі.

А от що опиралося – це варто знати наперед. Полотно в Zapier – це площина, яку тягають мишкою, а не список, тож у DOM існують лише ті вузли, які зараз видно. Перелічити кроки й пройтися по них циклом неможливо: до кожного треба доїхати, і читання перетворюється на фізичну працю з мишкою в руці. Умови фільтрів і вбудований код лежать на рівень глибше, за кнопкою «Edit Zap», а відкритий редактор створює чернетку поверх живої автоматизації. Читати чернетку безпечно, поки нічого не публікуєш, але на Zap-і лишається позначка, яку потім доведеться окремо піти й зняти.

Тиждень урятувало одне рішення щодо Zap-а на 99 кроків. Дев’яносто дев’ять кроків виявилися шістьма шаблонами, розмноженими копіюванням. Це був розгорнутий цикл: три гілки, кожна обробляє до шести позицій, і для кожної позиції повторюється та сама послідовність create-price → create-item → write-back. Прочитай по одному екземпляру кожного шаблону – і робота стискається з 99 панелей до 6, а в n8n на місці всіх копій стоїть один цикл по підформі з позиціями.

Агент перепише всі 99, якщо попросите, – радо, цілу годину. А вирішити, що правильне число – шість, лишається вам.

Переносиш схему – переносиш і баг

Вісімнадцять Zap-ів стали одинадцятьма сценаріями, і схудло все через одну властивість платформи, з якої ми йшли. У Zapier немає розгалужень. Тож одна логіка з двома умовами живе як два Zap-и, і кожен із них ніяк не може дізнатися, що існує інший.

Саме так і з’явилися 889 пар дублікатів. Два Zap-и створювали записи інвойсів з різних подій Stripe, третій – як побічний ефект, коли фіксував платіж, і кожен із трьох перевіряв лише одне: чи не спрацьовував він уже сам. У n8n це виправлено на рівні будови: створювати такий запис має право рівно один сценарій, перед записом він шукає дублікати і серед останніх записів, і в повному пошуковому індексі, а сценарій, що фіксує платежі, знаходить інвойс або чекає, потім б’є тривогу – і нічого не створює.

що змінилося між двома платформами 18 Zap-ів, 11 сценаріїв
як було в Zapier
  • одна логіка з двома умовами живе як дві автоматизації, які не бачать одна одну
  • три автоматизації створюють записи одного типу, і жодна не знає про інші
  • тригер чекає на подію «запис змінився»; пропущена подія зникає назавжди
  • прапорець «готово» скидається ще до вихідного виклику, який може й не вдатися
  • крок із налаштуванням «продовжувати при помилці» фарбує запуск у зелений, навіть коли API нічого не зробило
  • чому все зроблено саме так, пам’ятає хіба чиєсь листування в месенджері
як стало в n8n
  • один сценарій, один вузол розгалуження, обидві умови видно на одному полотні
  • створювати такий запис може рівно один сценарій, і перед записом він двічі шукає дублікати
  • більшість сценаріїв щодесять хвилин питають «що ще не доведено до кінця»
  • прапорець ставиться після того, як виклик повернув успіх
  • спільний обробник помилок пише в канал, а відповідь API розбирають за типами
  • на кожному сценарії є наліпка з назвою Zap-а, який він замінив, і з тим, що змінилося

Третій рядок я б переносив першим у будь-якій схожій міграції. Zapier слухав події, а подію, яку тригер пропустив, уже не повернеш. n8n здебільшого сам перепитує стан, тож черга роботи – це прапорець на самому записі, а черга із записів переживає і перезапуск, і викладку нової версії, чого не скажеш про чергу з подій. Перший же запуск нового сценарію синхронізації контактів за 3,8 секунди розгріб 40 записів, які чекали на шлях до Stripe, – найстаріший ще з вересня 2025 року. Ніхто й не знав, що вони чекають, бо модель на подіях не дає вам нічого, на що можна було б подивитися.

Самі перемикання зводилися до хвилини клацання з годинником перед очима. Для останньої пари я вручну вимкнув обидва Zap-и, дочекався підтвердження, приблизно за шістдесят секунд опублікував заміну, а потім пройшовся по Stripe, щоб переконатися, що жодне замовлення не провалилося в цю щілину.

Тестування набирає розмаху, коли тест перестає бути одним прогоном

Саме в перевірці сильна модель змінила характер роботи: вона зробила по кишені одразу кілька незалежних видів перевірки.

Уся історія разом. Замість питати, чи спрацював один запуск, питайте, скільки записів за всю історію мають цей дефект. Розслідування дублікатів пройшлося по всіх інвойсах, а це близько 51 000 записів, – і в цьому різниця між повідомленням про баг і вимірюванням. Воно ж зупинило небезпечне виправлення: спершу я запропонував видалити по одному інвойсу з кожної пари, а повна вибірка показала, що у двох половинах різні поля, тож видалення будь-якої з них губить дані.

Детектор, відточений до чистого розділення. Моя перша сигнатура пари дублікатів спрацювала на 9980 записах, і справжніх серед них було 889. Хибні – це імпорт даних 2023 року та інвойси, виставлені вручну. Переписувати сигнатуру, доки вона не почне чисто відділяти одне від одного, – це і є тест, а готова сигнатура потім стає щоранковою перевіркою за розкладом, тож регресія сама дає про себе знати, а не чекає, поки її знайдуть.

Код старої платформи, запущений локально. Вбудовані скрипти із Zap-ів я спершу проганяв у себе на справжніх вхідних даних, а вже потім переносив їхню логіку в сценарій. Один такий прогін зловив справжній баг у моєму власному перекладі цієї логіки.

Сусідні системи. Той самий факт перевіряється в Stripe, у CRM і в сховищі даних. Там, де три джерела розходяться, ви щось знайшли за будь-якого розкладу, і кілька з дванадцяти дефектів виринули саме там, а не в тестах, які я придумав.

Сусід на тому самому сервері. Після публікації одного сценарію його вебхук у Stripe мовчки не зареєструвався. Видав це інший сценарій на тому самому сервері, який теж запускається від Stripe: у той самий проміжок часу, на той самий платіж, він нормально відпрацював парну подію. n8n в обох випадках показував новий сценарій активним, з одним тригером, бо активацію він записує в себе ще до того, як пробує зареєструватися на боці Stripe. Прапорець активності фіксує, що ми попросили; список вебхуків у Stripe – чи це справді сталося. Допомогло зняти сценарій із публікації й опублікувати знову, і наступний платіж запустив його за 47 мілісекунд.

Жодну з цих п’яти перевірок моделі не довелося вигадувати. Від моделі треба було лише одне – щоб вона була дешевою. Запит по 51 000 записів, сигнатура, відшліфована за чотири заходи, локальний запуск чужого JavaScript, звірка трьох систем: кожне з цього – година людського дня, а таких було десятки. Коли кожна перевірка коштує годину, ви запускаєте дві, що здаються найперспективнішими. Коли хвилину – запускаєте всі, і це вже зовсім інше заняття.

Скільки треба одній людині і що вона збудувала б натомість

Оцінку я склав так.

Читання: приблизно 300 панелей зіставлення полів, по десять хвилин на кожну, бо в більшості від восьми до п’ятнадцяти зіставлених полів, а половина посилається на попередній крок за номером, тож звіряєш на ходу. П’ятдесят годин, плюс три проходи інвентаризації і фільтри, які відкриваються лише в редакторі чернетки. Три тижні.

Будівництво: одинадцять сценаріїв, у середньому по п’ятнадцять вузлів, для кожного тригера – облікові дані, які треба підключити, і вебхук, який треба зареєструвати. Від одного до двох днів на сценарій. Три тижні.

Перевірка: її обмежує те, як часто трапляються справжні події, а не те, наскільки завзято ти працюєш. Один із цих ланцюжків спрацьовує раз на два-три дні. Два-три тижні календарного часу, хоч що роби.

Аудит і прибирання: дванадцять дефектів, кожен – від кількох годин до кількох днів розслідування, а виправлення – це 854 з 889 пар дублікатів, злитих вручну.

Три-чотири місяці роботи однієї людини, повністю зайнятої лише цим, яка з першого дня знає обидві платформи і бізнес зсередини.

Але порівнювати так – хибно. Людина, яка робить це вручну, будує інший проєкт. Ніхто, переписуючи двохсоту панель зіставлень, не зупиниться спитати, чи не зашита на цій гілці валюта в код. Ручна версія виходить десь за шість тижнів, працює з першого ж дня і переносить усі дванадцять дефектів у цілості й схоронності, бо перенесення, яке вірно відтворює оригінал, – це успішне перенесення.

Тож чесно буде сказати так: ті самі два тижні купили зовсім іншу роботу – аудит, який принагідно закінчився міграцією. Дешеве читання змінює те, чим проєкт є, задовго до того, як воно змінить, наскільки швидко завершиться його запланована версія.

Один Zap досі ввімкнений, поки його власник вирішує, чи потрібне ще те, що він робить. А сценарій на заміну для лінійки продукту, де гроші списують без інвойсу, вже перевірено на тригері, на умові входу й на гілці пропуску, але гілка, яка справді записує дані, ще жодного разу не запускалася: їй потрібне справжнє замовлення, а такі приходять раз на два-три дні. Зранку перевірю.