Hi, I'm Sergei — Tech Lead / Senior PHP Developer
I work on the money-critical side of SaaS: billing, subscriptions, and payment integrations that run in production and handle real money. I know what breaks there — idempotency, duplicate webhooks, timeouts where you don't know if the payment went through, data that has to stay correct. Currently Tech Lead on a multi-tenant SaaS platform for real estate agencies, where I own the backend end to end. I shipped AI into that product: LLM-generated listing descriptions grounded in our own data, voice dictation, and a call-analysis pipeline (speech-to-text with diarization → summary → lead classification).
15+ years building SaaS products — beyond payments: large XML feeds, search, and complex business logic, plus a lot of legacy modernization: taking old codebases and making them maintainable.
What I am looking for: a product company with a modern PHP stack, where the backend is about correctness and integrations — billing, marketplaces, fintech, or a SaaS platform with complex business logic.
Based in Serbia (CET) — a full working day of overlap with European teams. Available for full-time B2B contracts: I invoice through my own company — SEPA or SWIFT, in EUR, the same way as any EU contractor.
Four problems from my current project
Payments from four providers, and receipts that have to match
Billing runs on four payment sources — three banks and a payment provider — accepting both card and QR payments. All four behave differently: different formats, different events, different guarantees about delivery. The first thing I built was one internal model of a payment, so nothing downstream has to know whose webhook it came from.
Taking the money is the easy half. The client operates through several legal entities, and which one issues the receipt is not a property of the payment: it follows from the type of contract with the customer combined with the type of contract with the agency involved. The same amount, paid the same way, can belong to a different entity with different tax details.
Receipts come from an external fiscal service that can be unavailable, so a receipt is never issued inside the payment request. The payment is recorded first, and the receipt is a separate job with retries. Refunds are the gap: there are none in the system today, they are done by hand. Once there are enough of them, they belong in the same pipeline as the receipts, not in a manual path beside it.
AI features in production
Realtors spend a large part of the day writing texts instead of selling, so I built AI into the product rather than around it.
For listings, the model generates a description from the real parameters in our database — rooms, area, floor, address. The facts come from us; the model only writes the text around them, and the realtor approves every draft before anything is published. He can also dictate the description instead of typing, which matters when you are not at a desk.
For calls, recordings go through a background pipeline: speech to text with diarization, then a model that returns a summary and a lead label. Before that nobody listened to the calls; now every call gets a summary.
Nothing runs automatically — every AI action is requested by a user, and the heavy work happens on a worker, never inside a request. Models are picked per task, so we do not pay premium rates for work a cheaper model does well. What is missing is measurement: we do not track classification accuracy yet, and managers correct a wrong label when they see one. That is the first thing I would instrument at higher volume.
Public search without touching the main database
Our platform has two kinds of users: realtors working in the back office, and anyone searching for properties on the public sites. Both ran on one MySQL database, and public search was slow — showing a single property card meant joining the property, the company, the realtor, the address and the photos.
I split the read model from the write model. MySQL stayed the source of truth and moved into a closed network, unreachable from the public side. For the public sites I build denormalized documents in MongoDB: one document holds everything a property card needs, so search does no joins at all. MySQL load dropped, public search got much faster, and the main database is no longer exposed to public traffic.
Documents are updated on write, and a separate job rebuilds the index — for structure changes, and as a repair tool. That direct write is the limit of the design: it holds because the volume is moderate. At a larger scale I would move the updates into a queue with retries.
Bringing development back in-house
When I joined, most of the development was done by outside contractors. It was slow and expensive — simple features took weeks, because every task started with explaining the domain. I proposed to the CEO that we bring development in-house, and he agreed.
Today a small in-house team owns the system end to end, and nothing waits for an external vendor. Features ship faster, the codebase is finally consistent, and the company spends less on development than before.
What made it work was domain knowledge rather than speed: we already knew how the business operates, so there was no translation layer between a request and the code.
Current Stack & Tools
• Backend: PHP 8.4, Symfony 7, Yii 2, Go
• AI Integration: OpenAI API, LLM-based automation, Speech-to-Text pipelines (Whisper, diarization)
• Databases & Search: MySQL/MariaDB, PostgreSQL, MongoDB, Elasticsearch, ClickHouse
• Caching & Queues: Redis, Memcached, RabbitMQ
• DevOps: Docker, GitLab CI/CD, GitHub Actions, Nginx (rate limiting, caching, reverse proxy)
• Frontend: JavaScript, React, Vue.js