How Vpodarok evolved from a monolith built on Yii1 to a service‑oriented architecture with its own processing.
The Vpodarok project started as a regular online store selling gift certificates using Yii1. Over time, it evolved into an ecosystem with B2B showcases, APIs, and complex business logic. We’ll tell you how the team gradually moved the core into a separate service called Processing, why the Data Connector was needed, and what compromises had to be made when transitioning to a service‑based model.
How Vpodarok Evolved from a Monolith into a Service-Based Architecture
The Vpodarok project started as a simple online gift certificate store built on Yii1. Over time, it evolved into an ecosystem with B2B storefronts, APIs, and complex business logic. In this article, we explain how the team gradually extracted the core into a separate Processing service, why Data Connector became necessary, and what compromises had to be made during the transition to a service-oriented model.
How It All Started: A Monolith That Became an ERP
The first versions of Vpodarok were built on Yii1. It was a classic online store: choose a certificate, place an order, and send it by email.
Over several years, dozens of teams worked on the codebase one after another. The code became increasingly complex, accumulated inconsistent solutions, and became difficult to maintain. At the same time, the product continued to grow:
-
B2B storefronts were introduced;
-
features for legal entities and reporting were added;
-
APIs and 1C integrations expanded;
-
PDF generation and partner mailings appeared.
Our team took over the project and, while continuing to support the existing solution, started building a new project on the Laravel framework. Later, a smooth transition to the new solution was completed, and the old system was retired.
Time passed, and the new application also continued to accumulate functionality. Several teams, including ours, were involved in the project.
The Laravel application gradually turned into a universal system handling everything: user scenarios, certificate generation, and the entire back office. The product started to resemble an ERP system — but without clear boundaries between areas of responsibility.
What this led to in practice:
Any change could affect dozens of other parts of the system. New developers struggled to understand the logic and dependencies. Supporting every new feature required manual synchronization with multiple components.
When It Became Clear That Something Had to Change
The turning point was a series of ongoing performance issues.
During large marketing campaigns or peak corporate orders, the system started experiencing failures:
-
server load increased;
-
database queries became slower;
-
duplicate requests from browsers and bots appeared;
-
security requirements grew — vulnerabilities and script attacks through public routes became a concern.
The team realized that the logic had to be gradually extracted from the monolith. But not through a complete rewrite from scratch — rather, through a step-by-step architectural evolution.
First Stage: Stabilizing the Existing System
We started by eliminating bottlenecks.
What was done:
-
Database — moved to a separate server after measuring latency between data centers.
-
Spam protection — introduced Laravel throttle mechanisms and replaced Google reCaptcha with a local solution suitable for the Russian market.
-
Monitoring — Laravel Telescope helped track application load and behavior.
-
Notifications — critical errors started being sent directly to the team's Telegram channel.
At the same time, some of the most resource-intensive operations were moved to asynchronous RabbitMQ queues.
For example, certificate activation, which previously ran through cron jobs, was moved to supervisor workers processing tasks in multiple threads. This immediately improved system stability and reduced the load on the monolith.
Second Stage: Launching Our Own Processing Service
The key decision was launching a new service — Processing.
It became an isolated backend application, independent from the user interface and without direct external access. Business-critical functions were gradually moved into it:
-
orders and transactions;
-
certificate generation;
-
payment gateway and issuer integrations;
-
data validation and authorization;
-
logging and throttling.
Processing became the core engine of the entire system.
An important detail: Processing itself does not expose any public APIs. Communication with it happens only through a dedicated gateway — Data Connector.
It acts as a facade, an aggregator for legacy APIs, and a router for client requests. As a result, even old API v1/v2 integrations continued working without interruptions, although they were already communicating with the new system underneath.
How Orders Are Processed Now
The order lifecycle has been completely transformed.
Step by step:
-
The customer creates an order through API v3.
-
Depending on the payment method, either funds are deducted from the customer's balance or an invoice is created in the payment aggregator and processed through a callback.
-
After payment confirmation, Processing sends a task to the queue.
-
A worker generates an encrypted PDF certificate and stores it in private storage.
-
The document can be received through an API response, webhook, email, or SMS — depending on the configuration.
-
Certificate activation and redemption also go through Data Connector: it checks the card status and creates a deactivation task in Processing.
Results: What Changed in the Architecture
The most important result was the separation of business logic and interfaces.
Now storefronts, admin panels, partner solutions, and the online store operate independently from each other. Everything related to business processes is concentrated inside Processing.
It can be scaled separately, updated separately, and is no longer tied to the web frontend.
Queues, logging, and notifications also became independent services.
This allowed us to:
-
reduce the load on the main application;
-
significantly decrease the support team's workload;
-
onboard new developers faster — responsibilities became clearer, documentation became more structured, and testing became more predictable.
Not Only Benefits: Honest Thoughts About Trade-offs
Like any transition to a service-based architecture, this journey required significant effort.
What became more complicated:
-
DevOps — additional responsibilities appeared: monitoring, containerization, and maintaining multiple components.
-
SLA management — became more complex: even a minor failure in one of ten services could affect the availability of the entire system.
-
Communication between services — requires careful handling of latency and fault tolerance.
-
Internal expertise — required deeper knowledge of security, message brokers, database types, and data synchronization.
However, these costs proved worthwhile.
According to internal metrics, the time spent supporting legacy code was reduced by half, while performance increased several times.
What’s Next
The team continues moving toward a fully service-based architecture.
Upcoming plans:
-
complete separation of storefronts and the online store;
-
expansion of the public API;
-
implementation of additional security and monitoring layers;
-
using Processing as a ready-made product — with its own interface, SLA, and autonomous deployment for corporate customers.
Conclusion
The transition from a monolith to a service-based architecture in Vpodarok was not a chaotic rewrite but a planned evolution driven by business requirements.
The architecture changed because the product grew beyond a single storefront and became a platform.
Today, the system is ready for growth, scaling, and new solutions without the fear of “breaking everything”.
Although the journey took more than a year, it became the foundation for the product’s long-term sustainable development.
We wish everyone successful projects! We would be happy to receive your subscriptions and comments.