When I joined Y-Proximité, after picking up the many warning signs described in this series of posts, I felt the need to start migrating our multi-tenant (1 DB = X customers), white-label “CMS” application built for site networks. Today it hosts about 2,000 sites/landing pages.
You can read in some places that a rewrite is evil. I decided to tell the story of our migration (politically less abrasive than a rewrite), which took 2 years. Here is my logbook of the migration to “Yprox v2”, covering several topics.
- I. Migration: The reasons
- II. Migration: The continuous migration process
- III. Migration: Taking stock
Why we migrated
1. Deprecated code
The “Yprox” project was created on Symfony 2.0-ALPHA.
Back then, Symfony was tagged with pre-SemVer tags such as “vPR12”.
Forms relied on a version of the Form component that has nothing in common with today’s. A backup of that code is available here for the adventurous.
Come on, you remember: a distant era between the Symfony 1.4 craze and a not-yet-released Symfony 2, which brought its share of worries (“where did my admin generator go?”, “dependency injection, WTF IS THAT”). Back then, this is how you did it:
<?php
public function configure()
{
...
$this->add(new TextField('first_name'));
$this->add(new TextField('last_name'));
$this->add(new ChoiceField('delivery_country', array(
'multiple' => false,
'choices' => $countriesForSelect,
'value_transformer' => $countriesTransformer,
)));
}
About 70% of the forms were built on obsolete, and therefore unmaintained, code. The project was upgraded all the way to Symfony 2.8, but it still hadn’t shed the technical debt of those “legacy” forms (among other things).
2. A long, hard ramp-up
Getting up to speed on the old version is a bit like climbing Everest. Plenty of things are obscure without help from the original developers, and before you can ship your first patch, you have to be sure you’ve grasped the application’s many concepts and challenges (inheritance, multi-tenancy, networks, white-labeling…).
Every production release, at a pace of 1 every 2 weeks, is a bit of a gamble and a source of stress. (spoiler: in the next post, I explain how we got to 32 deployments a day)
3. A sprawling structure
The multi-tenant application is actually 2 apps:
- An admin to manage your site(s) and push content to the network’s member sites.
- A front end that renders the requested site based on its domain.
Click the image to see a second structure inside the initial one:

A SiteKernel and an AdminKernel are in charge of loading the “right” bundles depending on the context. But that separation isn’t real, since everything is mixed together.
Nearly 300,000 lines of JS and 130,000 lines of PHP live in this “spaghetti” architecture (src/Ylly).

4. The original developers are gone
The company’s acquisition by Fiducial and its move to Lyon cost it the last of the product’s founding developers. Despite solid core principles, they left behind little documentation and a handover period that wasn’t long enough. To me, it was important to “take back ownership of the code” so we could meet business needs better and faster.
5. An outdated design
Let’s face it, a code migration means nothing to users. So when you pitch the project to decision-makers, one more argument about a responsive, better-suited design helps you score points (and spares your retinas every day).
In short, the decision to migrate is a subjective one, and always tied to a specific context (the existing team, skills, technical debt, code quality, expectations…).
Read on: II. Migration: The continuous migration process

