Сергій Рудюк | Засновник K2
Як «Корпорація 1», модульна K2 на Delphi, PHP і досвід 1С привели до платформи на Python та TypeScript
Я понад 30 років розробляю програмне забезпечення. Починав ще тоді, коли комп’ютер був далеко не в кожному офісі, а слово «хмара» переважно означало прогноз погоди. За цей час пройшов через Clipper, Basic, Pascal, Delphi, 1С, PHP, Python, TypeScript і чимало інших технологій. Працював із базами даних, створював облікові системи, програми для виробництва, логістики та автоматизації підприємств.
За всі ці роки мене не полишала одна ідея: як невеликою командою робити великі, складні системи, не починаючи кожен проєкт із нуля? Щоб система підлаштовувалася під підприємство, а не підприємство ламало свої процеси під програму. Щоб клієнту не потрібні були надмірні витрати на сервери, ліцензії та супровід. І щоб через п’ять або десять років продукт можна було продовжувати розвивати, а не знову переписувати.
Сучасна K2 Platform, або просто K2, — не трирічний стартап, який раптом народився на Python. Це чергове покоління системи, яку ми будували, використовували, перебудовували й удосконалювали десятиліттями. Три роки тому ми почали нову реалізацію ядра на Python і TypeScript. Але сам задум значно старший. Історія його розвитку пояснює значно більше, ніж будь-який перелік модулів.
Корпорація 1. Коли швидка розробка справді була швидкою
Першу серйозну реалізацію цього задуму ми зробили в «Корпорації 1». Основною технологією була Delphi. І результатів на ній вдалося досягти чималих: ми створювали складні прикладні системи, накопичували власні бібліотеки та використовували готові механізми в нових задачах.
Мене досі дивує, як добре Delphi навчала об’єктно-орієнтованого програмування. Поставив кнопку на форму — ось тобі об’єкт. Є клас, властивості, методи, події. Змінив властивість — бачиш результат. Створив ще одну кнопку — отримав інший екземпляр того самого класу. Для людини, яка вивчає ООП, така наочність інколи корисніша за десяток розділів підручника.
Для бізнесових програм Delphi була майже ідеальним інструментом свого часу. Форми, таблиці, робота з базою, обробники подій, звіти — усе близько одне до одного. Можна було швидко перейти від задуму до робочого екрана, а далі займатися реальними правилами підприємства.
Поступово ми почали помічати, що цінність має не лише готова програма, а й сам інструментарій для її створення. Якщо один раз розробити компонент документа, пошук, механізм прав або складний грид, його можна використовувати багато разів. Саме так з’являється шанс малими силами братися за великі задачі.
Проте зростання успішної системи швидко показує слабкі місця її архітектури. Чим більше напрацювань, тим складніше узгоджувати зміни й підтримувати різні продукти. Потрібні модулі, керована взаємодія між ними, зрозуміле оновлення і можливість розширювати рішення без копіювання всього коду. Так ми підійшли до наступного покоління.
Корпорація 2. Не нова назва, а інша архітектура
Ми створили «Корпорацію 2» — K2. І вона теж спочатку була на Delphi. Але цього разу ми свідомо закладали модульність. Хотіли, щоб продукт складався з частин, які можуть розвиватися окремо, підключатися за необхідності та багаторазово використовуватися в різних рішеннях.
Сама назва K2 існує з того часу. Слово Platform ми почали активно додавати набагато пізніше, коли на технологічній основі з’явилося багато окремих продуктів: K2 ERP, K2 CRM, K2 WMS, K2 LMS, K2 CMS та інші. Треба було пояснити, що K2 — передусім основа, на якій усе це працює, а не лише назва чергової облікової програми.
Модульність на Delphi дала відчутні переваги, але не скасувала обмежень екосистеми. Розвиток Інтернету підштовхував нас до вебзастосунків. Ми додали PHP, і певний час співіснували дві технологічні частини: Delphi та веб. Це дозволяло рухатися вперед, але мало й ціну: два світи, різні інтерфейси, різні інструменти, відмінності в реалізації спільних задач.
Зрештою ми відмовилися від Delphi в новому поколінні продукту й залишили PHP як основну технологію. K2 на PHP не зникла: вона продовжує існувати, поки її напрацювання та функціональність поступово знаходять місце в новій архітектурі. Та й попередні покоління не були даремною роботою. Саме завдяки їм ми отримали величезний набір перевірених бізнесових алгоритмів і точно знали, що хочемо перенести далі.
Чому я так довго не хотів відмовлятися від Delphi
Від Delphi було непросто відмовитися. Вона була знайома до дрібниць, у нас працювали складні продукти, а багато власних компонентів уже пройшли випробування замовниками. Коли інструмент дозволяє швидко виконувати роботу, його не міняють лише заради моди на нову мову.
Але мої технологічні вимоги змінювалися. Я давно перейшов на Linux на більшості комп’ютерів. Мене влаштовували серверні можливості Linux, контроль над системою, відсутність обов’язкової Windows на кожному робочому місці. На мої потреби Linux підходив на всі 120%. Хотілося і розробляти, і запускати продукти на різних ОС, а не тримати окремий Windows-комп’ютер лише тому, що без нього не стартує IDE.
У Delphi був ще один неприємний для команди бік: відтворення робочого середовища. Потрібно встановити потрібну версію RAD Studio, підібрати компоненти, їхні версії та залежності, налаштувати бібліотеки й шляхи. На одному комп’ютері працює, на іншому — шукай, чим саме відрізняється конфігурація. Іноді новому розробнику доводилося спершу освоювати мистецтво встановлення середовища, а вже потім писати програму.
У вузькоспеціалізованих компонентах також накопичувалася залежність від конкретних авторів і версій. Переходиш на іншу ОС або оновлюєш інструмент — і той самий код вже не збирається. У масштабному продукті це перетворювало кожен технологічний крок на окремий проєкт.
Додавалася й проблема найму. Фахівців із глибоким досвідом Delphi та нашим набором компонентів було все важче знаходити. Я хотів, щоб розробник приходив зі знанням поширених технологій і далі вивчав специфіку K2, а не починав із освоєння цілого набору історичних залежностей.
RAD Studio 10.2. Останній серйозний експеримент
Після переходу до вебу я не перестав шукати спосіб зберегти Delphi. Останні серйозні спроби робив на RAD Studio 10.2. Навіть створив на ній потужний, цікавий продукт. І саме на цьому етапі остаточно зрозумів, що стара технологічна основа не дозволить досягти поставлених цілей без непропорційних витрат часу.
RAD Studio 10.2 принесла компілятор для Linux, орієнтований передусім на серверні 64-бітні застосунки. Це був реальний технологічний крок, але він не означав, що наявні графічні програми на VCL автоматично запрацюють у Linux. Для кросплатформених графічних інтерфейсів існували інші механізми й додаткові рішення, а наш накопичений компонентний код був переважно розрахований на Windows.
Приблизно 70–80% компонентів, які ми використовували в тих проєктах, не працювали під Linux без заміни чи перероблення. Компілятор сварився на звичні класи й компоненти. Навіть прості на вигляд операції з файлами створювали проблеми, коли за ними ховалися Windows API або непереносимі залежності. Тут немає твердження, що Delphi не вміє працювати з файлами під Linux: проблема була в реальному коді та його історії.
Я почав витрачати на пошук обхідних рішень більше часу, ніж знадобилося б для написання відповідного функціоналу наново під потрібну ОС. Тоді постало просте запитання: навіщо мені кросплатформеність, за яку доводиться платити майже повною переробкою застосунку?
Зрештою я закрив і цей продукт на RAD Studio 10.2. Прикро було не через інструмент, а через вже вкладену роботу. Проте продовжувати означало обслуговувати технічні обмеження замість розробки нових можливостей. Для моїх цілей це стало остаточним аргументом.
Чого мене навчила 1С: три способи роботи, одна логіка
Ми багато працювали і з 1С. Її головна перевага для мене була не в бухгалтерських документах як таких, а в самій ідеї платформи прикладних рішень. Довідники, документи, регістри, форми, звіти та права мають спільні механізми. Розробник концентрується на бізнес-правилах.
Дуже цікавою була модель, коли одну прикладну логіку можна використовувати через тонкий, веб- та мобільний клієнти, хоча для мобільного середовища, звісно, існують власні вимоги та обмеження. Я хотів рухатися в тому самому напрямку.
Навіщо окремо створювати настільну програму, потім вебверсію, потім мобільну, а після зміни розрахунку собівартості виправляти три різні реалізації? А якщо в одному клієнті виправили, а в другому не встигли? У результаті бухгалтер і працівник складу отримують різні цифри. Обидві програми при цьому можуть вважати себе цілком справними.
Мета була іншою: спільна бізнес-логіка, спільні дані, різні інтерфейси під конкретне робоче місце. У складського працівника на смартфоні — сканування, кілька великих кнопок і мінімум зайвих дій. У бухгалтера — повноцінні журнали й документи. У керівника — аналітика. Але правила роботи системи мають залишатися узгодженими.
Ми вирішили перевершити 1С за сукупністю важливих для нас характеристик: швидкість прикладної розробки, гнучкість, модульність, кросплатформеність, незалежність від специфічної IDE, робота з великими БД, контроль оновлень і відкритість до сучасних бібліотек та інтеграцій. Це наша мета, а не заява про вже доведену перевагу в кожному можливому тесті.
Нове покоління K2: чому ми почали з ядра
Близько трьох років тому ми розпочали повну технологічну перебудову на Python, TypeScript і PostgreSQL. Але, на відміну від першої спроби створення системи багато років тому, цього разу вже мали досвід усіх попередніх поколінь. Ми заздалегідь знали, де найчастіше виникають проблеми при зростанні бізнесового продукту.
Тому не почали з того, щоб намалювати красиву ERP. Почали з ядра, яке дозволяє перевизначати поведінку, розширювати стандартні механізми, підключати модулі та зберігати індивідуальні доробки. Універсальний механізм має бути достатньо сильним, щоб покривати поширені сценарії, і достатньо гнучким, щоб не заважати специфічному процесу клієнта.
Це ключова ідея нашої статті «Програми — як одяг»: серійний продукт зручний виробнику, але не завжди точно підходить підприємству. А повністю індивідуальне програмування надто дороге, якщо починати з нуля. Тож ми хотіли мати основу, яка дозволяє поєднати готові механізми з точним налаштуванням під конкретні потреби.
У K2 платформа та прикладні рішення розділені за відповідальністю. ERP, CRM, WMS, LMS, CMS, інтернет-магазин, виробництво, зарплата й кадри, ТОІР та інші напрями використовують спільні технологічні механізми. Водночас конкретна галузева логіка не повинна без потреби розростатися всередині ядра. Інакше за кілька років ми знову отримали б важкий моноліт — тільки цього разу власноруч і на новішій мові.
Компоненти, які справді економлять час
Delphi навчила мене цінувати готовий візуальний компонент. Цю ідею ми перенесли у веброзробку, створивши потужні RIA-компоненти. Складний грид — це не просто таблиця з кількома колонками. Це фільтрація, сортування, групування, редагування, підсумки, зв’язки, навігація, робота з великими масивами даних. Писати це наново для кожного довідника було б дивною витратою робочого часу.
У K2 розробник може підключати такі механізми через готові компоненти й декларативні описи. Аналогічно з формами, документами, журналами, друкованими формами та дизайнером друку. Мета — дати можливість однією командою підключити складну типову функціональність, а час витратити на бізнес-правило, якого немає в жодному стандартному компоненті.
Ми відразу передбачили ORM і різні типи даних, щоб прикладний код не перетворювався на нескінченне повторення однакових SQL-операцій. Для роботи зі структурою даних створили графічний ER-редактор, пов’язаний із декларативними моделями, міграціями та механізмами створення типової прикладної структури. Для бізнес-процесів — BP-редактор, у якому можна побачити послідовність кроків, умови переходів і взаємодію об’єктів.
Складні розрахунки, специфічні алгоритми та інтеграції реалізуються на Python. Ми принципово не хотіли обмежувати можливості платформи тим, що передбачили у візуальному конструкторі. Якщо бізнес придумав щось нестандартне — програміст повинен мати змогу це зробити, не розбираючи всю платформу на частини.
Поруч із формами й документами розвивали звіти, дизайнер друкованих форм, PivotGrid, BI та аналітичні панелі. Та сама інформація повинна бути корисною і в операційній роботі, і для прийняття рішень. Для цього не потрібно щоразу створювати нову програму.
Велика база даних не повинна стати сюрпризом
Ми не вперше автоматизуємо великі підприємства. Добре знаємо, як змінюється поведінка програми, коли замість кількох тисяч документів з’являються десятки тисяч щодня, а база займає сотні гігабайтів. Запит, який блискавично працював на тестових даних, у реальній експлуатації може перетворитися на серйозну проблему.
Тому ще на початку нового покоління передбачили детальне логування на рівні бази даних, контроль змін та секціонування великих таблиць. Основною СУБД стала PostgreSQL. Її можливості для транзакцій, індексування, секціонування та аналізу запитів відповідають нашому напряму. Логування допомагає розбиратися в тому, що сталося, а секціонування — керувати великими наборами даних. Воно, звісно, не замінює грамотного проєктування схеми й оптимізації SQL.
Платформа повинна бути придатна не лише для великих інсталяцій. Невелика задача має запускатися без зайвого господарства, а велика — масштабуватися з відповідною інфраструктурою. Я ніколи не хотів змушувати малого клієнта купувати архітектуру великого холдингу. І навпаки, не хотів закладати штучну стелю для систем, які зростатимуть роками.
Модульність, Git і власна система оновлення
Модульність ми заклали від самого початку. У кожного модуля є своя історія змін і версій, а вихідний код ведеться в окремому Git-репозиторії. Це дозволяє різним розробникам працювати з окремими частинами системи, повторно використовувати компоненти та розуміти, що змінилося між релізами.
Але модульність без оновлень — лише половина справи. Коли у вас одна програма, нову версію ще можна встановити вручну. Коли є десятки модулів і багато інсталяцій із власними доробками, ручний підхід дуже швидко починає з’їдати весь ресурс команди.
Саме тому K2 Update ми створювали паралельно з ядром. Каталог компонентів, історія версій, механізми постачання оновлень і контроль життєвого циклу модулів — усе це не запізніла надбудова. Ми хотіли, щоб програмний продукт міг отримувати нові функції багато років, а оновлення в ідеалі були максимально автоматизовані й керовані.
Це не означає, що складна ERP повинна оновлюватися без тестування в будь-який момент. Сумісність, міграції структури, залежності та клієнтські зміни вимагають дисципліни. Проте наявність власної системи оновлення дає нам основу для такої дисципліни, а не змушує щоразу вигадувати процедуру доставки змін.
Для мене це принципово: платформа призначена не лише для першого запуску, а для довгого життя. Сьогодні рішення може бути невеликим сервісом, а згодом перетворитися на велику систему. Воно повинно мати шлях розвитку.
Linux, Python і свобода вибору робочого місця
Один із найприємніших результатів — тепер розробники K2 працюють у різних операційних системах і різних IDE. Комусь зручний Linux, комусь Windows; хтось використовує PyCharm, хтось VS Code. І це не проблема, яку треба вирішувати управлінським наказом. Важливо, щоб усі працювали з узгодженим кодом, версіями залежностей, тестами й правилами команди.
Для звичайного Python-коду кросплатформеність часто значно простіша, ніж перенесення старого нативного Windows-застосунку з великим набором сторонніх компонентів. Там, де бібліотеки й залежності підтримують потрібну ОС, достатньо підготувати середовище. Звісно, нативні драйвери, робота з обладнанням і системні API можуть потребувати окремого коду — чудес немає.
Вебархітектура з TypeScript і Vue додатково відокремлює користувацький інтерфейс від серверної логіки. Основні бізнес-правила працюють на сервері, а браузер, десктопний спосіб доступу чи мобільний застосунок реалізують потрібний сценарій. Для касового застосунку ми, наприклад, розвиваємо офлайн-роботу з наступною синхронізацією. Це окремий технічний виклик, але він не змушує нас створювати абсолютно незалежну бухгалтерську або складську логіку.
Перевага поширеного стека відчутна і під час залучення людей. Розробнику з досвідом Python, TypeScript, SQL та Git потрібно вивчити архітектуру K2, але не нову закриту мову й один-єдиний спеціалізований редактор. Це пришвидшує розвиток команди й дозволяє залучати сучасні бібліотеки — від інтеграцій до аналітики й AI.
Поступова модернізація замість стрибка в невідомість
Найцінніше в старій програмі часто не її інтерфейс і навіть не код. Це бізнес-правила, накопичені дані, історія рішень та винятки, про які вже не пам’ятає ніхто, крім системи. Ми добре знаємо це за власними поколіннями К1 і К2 та за роботою з 1С, BAS, Access, Excel, Delphi і PHP.
Тому розвиваємо реверс-інжиніринг, аналіз структури даних і перенесення прикладної логіки. Для поступового переходу є K2 Реплікатор, який допомагає налаштовувати обмін і синхронізацію даних із різними джерелами. Це дозволяє, наприклад, спершу створити новий вебкабінет чи мобільний модуль, не вимикаючи одразу всю стару ERP.
Звісно, перенесення потребує зіставлення структур, перевірки даних і бізнес-логіки. Чарівної кнопки, що правильно перепише будь-яку систему з усіма історичними винятками, немає. Але завдяки моделям, компонентам та інструментам інтеграції ми можемо робити модернізацію поетапно й контрольовано.
Це одна з важливих переваг для клієнта: нову технологію можна вводити поступово, зберігаючи безперервність роботи підприємства.
Економіка платформи: великі задачі малими ресурсами
Я завжди хотів, щоб технологія допомагала скорочувати витрати, а не створювала нові обов’язкові платежі. Використання Linux, Python, PostgreSQL та відкритих бібліотек зменшує залежність від комерційних ліцензій на операційні системи, середовище виконання й базову інфраструктуру. Вебклієнт не потребує встановлення спеціального Windows-застосунку на кожне робоче місце.
K2 може працювати в хмарі, на власних серверах замовника або в гібридному середовищі. Це дозволяє підбирати інфраструктуру під реальні вимоги. Невеликому підприємству не потрібен дорогий серверний парк лише для того, щоб вести кілька довідників і документів. Великому ж клієнту може знадобитися розподілена інфраструктура, резервування, інтеграції й окремі правила інформаційної безпеки.
Водночас не варто плутати відкриті технології з безкоштовністю всього рішення. Ліцензія K2, впровадження, розробка адаптацій, адміністрування та підтримка мають власну економіку. Я говорю про можливість усунути зайві залежності й використати кошти на те, що справді приносить користь.
І для команди, і для замовника найпомітніший виграш у повторному використанні. Складний грид, ORM, друковану форму, механізм доступу чи оновлення ми не програмуємо знову для кожного клієнта. Це дає невеликій команді можливість реалізовувати більші за масштабом проєкти. Саме таку економіку розробки я хотів отримати понад 30 років.
Чи не простіше було взяти готовий фреймворк?
Певно, знайдуться розробники, які запитають: а навіщо створювати платформу, якщо вже існують Django, FastAPI, .NET, готові UI-бібліотеки, ORM і системи управління процесами? Запитання цілком справедливе. Для окремого застосунку готовий стек може бути найкращим рішенням.
Але в нас інша задача. Нам потрібна не просто бібліотека для HTTP-запитів, генерації форм чи доступу до БД. Потрібен узгоджений набір механізмів для прикладних продуктів: від ER-моделі, документів і прав доступу до великих гридів, друку, бізнес-процесів, модулів, оновлень, інтеграцій та поступової міграції.
Ми не стверджуємо, що на Delphi, C# чи інших технологіях неможливо зробити те саме. Зробити можна дуже багато. Питання в тому, яку архітектуру доведеться побудувати, скільки вона коштуватиме й наскільки зручно команда зможе її розвивати. Для нашої історії та цілей нове покоління K2 виявилося правильним вибором.
Власне ядро, звичайно, створює нові обов’язки. Ми самі відповідаємо за сумісність, безпеку, документування, тестування, продуктивність і розвиток. Але тепер ключові рішення щодо платформи перебувають під нашим контролем. Якщо потрібно змінити спільний компонент, ми можемо це зробити й використати результат у багатьох продуктах.
Чим стала K2 сьогодні
На сучасній технологічній основі ми вже створили K2 ERP, K2 CRM, K2 WMS, K2 LMS, K2 CMS, інтернет-магазин, інструменти для обліку, виробництва, управління персоналом, технічного обслуговування обладнання та аналітики. Є ER- і BP-редактори, конструктори форм і друкованих звітів, RIA-компоненти, механізми інтеграції, реплікації та оновлення. Різні модулі можна комбінувати залежно від задачі.
Істотна частина функціональності попередніх поколінь К1, К2 та PHP-рішень уже перенесена на нову платформу. Тож ми не просто придумали нову архітектуру і намалювали демонстраційні екрани. Ми вже живемо з наслідками власних архітектурних рішень: розвиваємо модулі, оновлюємо компоненти, розбираємо складні бізнесові випадки та працюємо з реальними даними.
Попереду ще багато роботи. Але сьогодні ми маємо головне: технологічну основу, на якій можемо будувати наступні рішення, не повертаючись кожного разу до початкової точки.
Delphi, дякую. Далі — K2
Чи шкодую я, що так багато років працював із Delphi? Ні. Вона навчила мене об’єктно-орієнтованого й компонентного підходу, показала цінність наочної швидкої розробки. Досвід 1С допоміг краще зрозуміти платформну автоматизацію бізнесу та спільну логіку для різних клієнтів. PHP дав можливість розвивати вебархітектуру. Python, TypeScript, Vue та PostgreSQL дозволили зібрати нове покоління на поширених технологіях без обов’язкової прив’язки до Windows і конкретної IDE.
Якби не було «Корпорації 1», навряд чи з’явилася б така «Корпорація 2». Без K2 на Delphi й PHP ми б не знали настільки добре, які рішення варто закладати в сучасне ядро від самого початку. Ці понад 30 років були не очікуванням нинішньої платформи, а безперервною роботою над тією самою ідеєю.
Три роки тому ми не вигадали K2 заново. Ми взяли накопичений досвід і перебудували технологічну основу так, як хотіли вже багато років.
Зараз, коли новий модуль можна розвивати на спільному ядрі, коли програмісти працюють у різних ОС та IDE, а складні інтерфейсні й серверні механізми не потрібно переписувати для кожного клієнта, я бачу, заради чого все починалося.
K2 Platform, або просто K2, для мене — можливість робити великі, складні й індивідуальні продукти невеликими ресурсами. А найцікавіше, що тепер ми можемо витрачати більше часу на самі задачі бізнесу, а не на спроби домовитися з компілятором, компонентами чи середовищем розробки.
Дізнатися більше
Матеріали про платформу: https://erp.kyiv.ua
Спробувати K2: https://cloud.corp2.eu
Документація: https://wiki.erp.kyiv.ua
Офіційний сайт: https://corp2.eu
From Delphi to K2 Platform: Over 30 Years in Search of Our Own Rapid Application Development System
Serhii Rudiuk | Founder of K2
How Corporation 1, modular K2 on Delphi, PHP, and experience with 1C led to a platform built with Python and TypeScript
I have been developing software for more than 30 years. I started when computers were far from commonplace in offices and the word “cloud” usually belonged in the weather forecast. Over that time, I have worked with Clipper, Basic, Pascal, Delphi, 1C, PHP, Python, TypeScript, and many other technologies. I have worked with databases and built accounting systems, manufacturing and logistics software, and enterprise automation solutions.
Throughout those years, one idea kept coming back to me: how could a small team build large, complex systems without starting every project from scratch? How could software adapt to the business rather than force the business to bend its processes around the software? How could clients avoid excessive spending on servers, licenses, and maintenance? And how could a product still be developed five or ten years later instead of being rewritten yet again?
Today’s K2 Platform, or simply K2, is not a three-year-old startup that suddenly appeared on Python. It is the next generation of a system we have been building, using, rebuilding, and refining for decades. Three years ago, we began a new implementation of its core in Python and TypeScript. The idea itself is much older. Its history tells you more than any list of modules ever could.
Corporation 1: When Rapid Development Really Was Rapid
Our first serious attempt to realize this idea was Corporation 1. Delphi was the main technology. We achieved a great deal with it: we built sophisticated business applications, accumulated our own libraries, and reused proven mechanisms in new projects.
I am still impressed by how effectively Delphi taught object-oriented programming. Place a button on a form, and there is your object. You have a class, properties, methods, and events. Change a property and you immediately see the result. Add another button and you have a different instance of the same class. For someone learning OOP, that visual clarity can be worth more than ten textbook chapters.
For business applications, Delphi was almost the perfect tool for its time. Forms, tables, database access, event handlers, and reports were all close at hand. You could move quickly from an idea to a working screen, then concentrate on the company’s real business rules.
Gradually, we realized that the value was not just in the finished application, but also in the tools used to build it. Develop a document component, search facility, permissions mechanism, or sophisticated data grid once, and you can reuse it many times. That is how a small team begins to tackle large problems.
But when a successful system grows, architectural weaknesses become visible very quickly. The more functionality you accumulate, the harder it is to coordinate changes and maintain different products. You need modules, controlled interaction between them, understandable updates, and a way to extend solutions without copying the entire codebase. That brought us to the next generation.
Corporation 2: More Than a New Name, a Different Architecture
We created Corporation 2, or K2. It also started on Delphi. This time, however, we deliberately designed for modularity. We wanted a product composed of parts that could evolve independently, be installed when needed, and be reused across different solutions.
The name K2 dates back to that period. We began using the word Platform much later, when the technological foundation had spawned several distinct products: K2 ERP, K2 CRM, K2 WMS, K2 LMS, K2 CMS, and others. We needed to explain that K2 was first and foremost the foundation they ran on, not just the name of another accounting application.
Modularity in Delphi brought tangible benefits, but it did not remove the ecosystem’s limitations. As the internet evolved, we were increasingly drawn toward web applications. We added PHP, and for a while the two technology layers coexisted: Delphi and the web. That helped us move forward, but it came at a cost: two worlds, different interfaces, different tools, and different implementations of shared tasks.
Eventually we moved away from Delphi in the new generation of the product and kept PHP as the main technology. The PHP-based K2 has not disappeared: it still exists, while its features and accumulated work gradually find their place in the new architecture. Nor was the work on previous generations wasted. It gave us a huge collection of tested business algorithms and a very clear understanding of what we wanted to carry forward.
Why I Was So Reluctant to Leave Delphi Behind
Walking away from Delphi was not easy. I knew it inside out, we had complex products running on it, and many of our components had already been tested by customers. When a tool lets you get work done quickly, you do not replace it simply because a new language is fashionable.
But my technical requirements were changing. I had moved most of my computers to Linux long before. I liked its server capabilities, the control it gave me over the system, and not having to require Windows on every workstation. Linux met my needs 120 percent. I wanted to develop and run products across operating systems, rather than keep a separate Windows machine solely because my IDE would not start without it.
There was another frustrating side of Delphi for the team: reproducing a development environment. You had to install the right RAD Studio version, select compatible components, versions, and dependencies, and configure libraries and paths. It worked on one machine; on another, you had to hunt for whatever was different. Sometimes a new developer had to master the art of installing the environment before writing a single line of application code.
Specialized components also created dependencies on particular authors and versions. Move to another OS or update a tool, and the same code no longer builds. In a large product, every technological step could become a project of its own.
Hiring became more difficult, too. Developers deeply familiar with Delphi and our particular set of components were increasingly hard to find. I wanted people to arrive knowing widely used technologies and then learn K2’s specifics—not start by deciphering an entire collection of historical dependencies.
RAD Studio 10.2: The Last Serious Experiment
Even after our move toward the web, I kept looking for a way to preserve Delphi. My last serious attempts were with RAD Studio 10.2. I even built a powerful, interesting product with it. That was when I finally understood that our old technology base would not let us achieve our goals without a disproportionate investment of time.
RAD Studio 10.2 introduced a Linux compiler aimed primarily at 64-bit server applications. This was a genuine technical step forward, but it did not mean existing VCL graphical applications would automatically run on Linux. Cross-platform GUIs required other mechanisms and additional solutions, while our accumulated component code had largely been written for Windows.
Around 70–80 percent of the components we used in those projects would not work on Linux without replacement or rework. The compiler complained about familiar classes and components. Even apparently simple file operations caused trouble when they concealed Windows API calls or non-portable dependencies. I am not saying Delphi cannot handle files on Linux; the problem was our real-world code and its history.
I began spending more time searching for workarounds than it would have taken to write the corresponding functionality from scratch for the target OS. That raised a simple question: what is the point of cross-platform support if you have to pay for it by practically rebuilding the whole application?
In the end, I shut down that RAD Studio 10.2 product as well. What hurt was not losing the tool; it was the work we had already put into the product. But carrying on would have meant servicing technical limitations instead of building new capabilities. For my goals, that settled the matter.
What 1C Taught Me: Three Ways to Work, One Set of Logic
We also worked extensively with 1C. Its greatest advantage, in my eyes, was not its accounting documents as such but the very idea of a platform for business applications. Catalogs, documents, registers, forms, reports, and permissions share common mechanisms. Developers can focus on business rules.
I found the model especially interesting in which one set of application logic could be used through thin, web, and mobile clients, although mobile environments naturally have their own requirements and limitations. I wanted to move in the same direction.
Why build a desktop application, then a web version, then a mobile version, only to fix three separate implementations whenever the cost calculation changes? And what if you fix it in one client but do not get around to the other? Suddenly, the accountant and the warehouse employee see different figures. Both applications may still insist that they are working perfectly.
The goal was different: shared business logic, shared data, and interfaces tailored to each workplace. A warehouse worker on a smartphone needs scanning, a few large buttons, and as few unnecessary actions as possible. An accountant needs full document registers and forms. A manager needs analytics. But the rules governing the system must remain consistent.
We set out to surpass 1C on the combined characteristics that mattered to us: application development speed, flexibility, modularity, cross-platform operation, freedom from a particular IDE, handling large databases, controlled updates, and openness to modern libraries and integrations. That is our goal, not a claim that we have already proved superiority in every conceivable benchmark.
The New Generation of K2: Why We Started with the Core
About three years ago, we began a complete technological rebuild using Python, TypeScript, and PostgreSQL. Unlike our first attempt many years earlier, this time we had experience from every preceding generation. We already knew where problems most often arise as business software grows.
So we did not start by drawing a beautiful ERP interface. We started with a core that supports overriding behavior, extending standard mechanisms, connecting modules, and preserving customer-specific modifications. A general-purpose mechanism has to be strong enough for common scenarios and flexible enough not to obstruct a customer’s unique business process.
That is the central idea of our article “Software Is Like Clothing”: a mass-produced product may suit the manufacturer but does not always fit a particular company. Fully bespoke software, on the other hand, becomes too expensive if you start from nothing. We wanted a foundation that combined proven mechanisms with precise adaptation to individual needs.
In K2, the platform and business applications have separate responsibilities. ERP, CRM, WMS, LMS, CMS, e-commerce, manufacturing, payroll and HR, maintenance management, and other areas use shared technical mechanisms. But industry-specific logic should not expand unnecessarily inside the core. Otherwise, a few years later, we would end up with another heavy monolith—this time one we had built ourselves, in a newer language.
Components That Actually Save Time
Delphi taught me the value of ready-made visual components. We carried that idea into web development by creating powerful Rich Internet Application (RIA) components. A sophisticated grid is not just a table with a few columns. It includes filtering, sorting, grouping, editing, totals, relationships, navigation, and working with large datasets. Rebuilding all of that for every catalog would be a strange use of developer time.
In K2, developers can connect such mechanisms through ready-made components and declarative descriptions. The same applies to forms, documents, registers, printable documents, and the print designer. The aim is to let a developer add sophisticated standard functionality with a single command and spend their time on the business rule that no standard component can cover.
We planned for ORM and different data types from the beginning, so application code would not become an endless repetition of the same SQL operations. To work with data structures, we created a graphical ER editor linked to declarative models, migrations, and mechanisms for generating standard application structures. For business processes, we built a BP editor that shows the sequence of steps, transition conditions, and interactions between objects.
Complex calculations, specialized algorithms, and integrations are implemented in Python. We deliberately did not want the platform’s capabilities to stop at whatever the visual designer happened to anticipate. If a business comes up with something unconventional, developers should be able to build it without taking the entire platform apart.
Alongside forms and documents, we developed reports, a printable-form designer, PivotGrid, BI, and analytical dashboards. The same information should be useful both in day-to-day operations and in decision-making. You should not have to create a new application every time.
A Large Database Should Not Come as a Surprise
This is not our first experience automating large enterprises. We know how an application’s behavior changes when a few thousand documents become tens of thousands per day and a database grows to hundreds of gigabytes. A query that runs instantly on test data can become a serious problem in production.
That is why we planned detailed database-level logging, change tracking, and partitioning of large tables from the beginning of the new generation. PostgreSQL became our primary DBMS. Its transaction, indexing, partitioning, and query-analysis capabilities align with our direction. Logging helps us understand what happened, while partitioning helps manage large datasets. Of course, neither replaces sound schema design and SQL optimization.
The platform also has to suit more than large installations. A small task should run without unnecessary infrastructure, while a large one should scale with the appropriate resources. I never wanted to make a small customer buy the architecture of a major holding company. Equally, I did not want to impose an artificial ceiling on systems that may grow for years.
Modularity, Git, and Our Own Update System
We built modularity into K2 from the outset. Each module has its own change and version history, and its source code is maintained in a separate Git repository. This allows developers to work on different parts of the system, reuse components, and understand what changed between releases.
But modularity without updates is only half the job. When you have one application, you can still install a new version manually. When you have dozens of modules and numerous installations with their own customizations, a manual approach quickly starts consuming the entire team’s capacity.
That is why we developed K2 Update alongside the core. The component catalog, version history, update delivery mechanisms, and module lifecycle management were never an afterthought. We wanted software products to gain new functionality for many years, with updates ideally as automated and controlled as possible.
That does not mean a complex ERP should update itself at any moment without testing. Compatibility, schema migrations, dependencies, and customer-specific changes require discipline. But having our own update system gives us a foundation for that discipline instead of forcing us to reinvent deployment every time.
This matters enormously to me: a platform is not only for the first launch, but for a long life. Today’s solution may be a small service and tomorrow’s a large system. It needs a path for growth.
Linux, Python, and the Freedom to Choose Your Workspace
One of the most satisfying results is that K2 developers now work across different operating systems and IDEs. Some prefer Linux, others Windows; some use PyCharm, others VS Code. This is not a problem to be solved by a management directive. What matters is that everyone works with consistent code, dependency versions, tests, and team conventions.
For ordinary Python code, cross-platform operation is often far simpler than porting an old native Windows application with a large collection of third-party components. Where the libraries and dependencies support the target OS, preparing the environment is usually enough. Naturally, native drivers, hardware interactions, and system APIs may require platform-specific code—there are no miracles.
The web architecture built with TypeScript and Vue further separates the user interface from server-side logic. Core business rules run on the server, while the browser, a desktop access method, or a mobile application provides the appropriate workflow. In our point-of-sale application, for example, we are developing offline operation with later synchronization. That is a technical challenge of its own, but it does not force us to create a completely independent set of accounting or warehouse rules.
The widespread technology stack also helps with recruiting. A developer who knows Python, TypeScript, SQL, and Git has to learn K2’s architecture, but not a new proprietary language and its one specialized editor. That makes it easier to grow the team and use modern libraries—from integrations to analytics and AI.
Gradual Modernization Instead of a Leap into the Unknown
The most valuable part of a legacy application is often neither its interface nor even its code. It is the business rules, accumulated data, history of decisions, and exceptions nobody remembers anymore—except the system itself. We know this well from our own K1 and K2 generations and our work with 1C, BAS, Access, Excel, Delphi, and PHP.
That is why we are developing reverse engineering, data-structure analysis, and application-logic migration. K2 Replicator supports a gradual transition by helping configure data exchange and synchronization with different sources. For example, a company can introduce a new web portal or mobile module before shutting down its old ERP.
Of course, migration requires mapping structures and validating data and business logic. There is no magic button that can correctly rewrite any system, including every historical exception. But models, components, and integration tools let us modernize gradually and under control.
For customers, this is an important advantage: they can introduce new technology step by step while keeping the business running.
Platform Economics: Big Projects with Small Teams
I have always wanted technology to reduce costs rather than create new mandatory expenses. Linux, Python, PostgreSQL, and open libraries reduce dependence on commercial licenses for operating systems, execution environments, and basic infrastructure. A web client does not require a special Windows application to be installed on every workstation.
K2 can run in the cloud, on the customer’s own servers, or in a hybrid environment. That allows infrastructure to fit actual needs. A small business does not need an expensive server fleet just to maintain a few catalogs and documents. A large customer, meanwhile, may need distributed infrastructure, redundancy, integrations, and dedicated information-security requirements.
At the same time, open technologies should not be confused with an entirely free solution. K2 licensing, deployment, custom development, administration, and support have their own costs. What I am talking about is removing unnecessary dependencies and spending money where it actually produces value.
For both our team and our customers, the greatest gain comes from reuse. We do not rebuild a sophisticated grid, ORM, printable form, access-control mechanism, or updater for every customer. That allows a relatively small team to deliver projects on a much larger scale. It is exactly the development economy I wanted to achieve more than 30 years ago.
Wouldn’t It Have Been Easier to Use an Existing Framework?
Some developers will surely ask: why build a platform when Django, FastAPI, .NET, ready-made UI libraries, ORMs, and workflow engines already exist? It is a fair question. For an individual application, an established stack may be the best choice.
But our task is different. We do not merely need a library for HTTP requests, form generation, or database access. We need a coordinated set of mechanisms for business products: from ER models, documents, and access rights to complex grids, printing, business processes, modules, updates, integrations, and gradual migration.
We are not claiming that the same things cannot be built in Delphi, C#, or other technologies. A great deal is possible. The question is what architecture must be built, how much it will cost, and how conveniently a team can keep developing it. Given our history and goals, the new generation of K2 proved the right choice.
An in-house core naturally brings new responsibilities. We are accountable for compatibility, security, documentation, testing, performance, and ongoing development. But the key platform decisions are now in our hands. If a shared component needs to change, we can change it and reuse the result across many products.
What K2 Has Become Today
On our modern technology foundation, we have already built K2 ERP, K2 CRM, K2 WMS, K2 LMS, K2 CMS, an online store, and tools for accounting, manufacturing, HR, equipment maintenance, and analytics. We have ER and BP editors, form and printable-report designers, RIA components, and integration, replication, and update mechanisms. Different modules can be combined according to the task.
A substantial part of the functionality from previous K1, K2, and PHP-based solutions has already been moved onto the new platform. We have not simply dreamed up a new architecture and drawn a few demonstration screens. We already live with the consequences of our own architectural decisions: developing modules, updating components, handling difficult business cases, and working with real data.
There is still a great deal to do. But today we have the most important thing: a technological foundation on which we can build the next solutions without returning to square one each time.
Thank You, Delphi. From Here, It’s K2
Do I regret spending so many years with Delphi? Not at all. It taught me object-oriented and component-based thinking and showed me the value of visual rapid development. Experience with 1C helped me better understand platform-based business automation and shared logic across clients. PHP let us develop a web architecture. Python, TypeScript, Vue, and PostgreSQL helped us bring the new generation together using widespread technologies without a mandatory tie to Windows or a particular IDE.
Without Corporation 1, Corporation 2 would probably not have become what it was. Without K2 on Delphi and PHP, we would not have known nearly as well what to build into a modern core from day one. Those 30-plus years were not spent waiting for today’s platform; they were continuous work on the very same idea.
Three years ago, we did not invent K2 all over again. We took everything we had learned and rebuilt the technological foundation the way we had wanted to for many years.
Now, when a new module can grow on a shared core, when developers work across different operating systems and IDEs, and when complex interface and server mechanisms do not have to be rewritten for every customer, I can see exactly what all this work was for.
To me, K2 Platform, or simply K2, means being able to build large, complex, highly customized products with a small team and limited resources. And the best part is that we can now devote more time to solving real business problems than to negotiating with a compiler, a set of components, or a development environment.
Learn More
Platform articles and materials: https://erp.kyiv.ua
Try K2: https://cloud.corp2.eu
Documentation: https://wiki.erp.kyiv.ua
Official website: https://corp2.eu
