Worklog for task "Migrate the website to a new engine"
Legacy DB Structure: The "Just Connect" Hypothesis is Being Re-evaluated
After running it locally, we examined the actual structure of the existing MySQL database. The scale of the legacy system turned out to be significantly larger than what was visible from the Docker stack alone: 250 tables, approximately 198k rows, and ~82 MiB of data.
Out of the 250 tables, about 150 have the old MODX prefix fSdf12_. This represents a large system layer of MODX itself and Extras installed over the years: ACL/policies, contexts, manager/dashboard, media sources, package transport, lexicon, sessions, users/groups, billing/shop modules, society, SDK/importer, search, monitoring, GeoIP, and other subsystems. A significant portion of these tables are empty or contain literally just a few records, but during legacy analysis, they still look like a potentially significant part of the system.
Separately, there is another historical model layer: dozens of Prisma-style relation tables _...; many of them are currently empty. Traces of sequential migrations and entity duplication are also visible: for example, old and new variants of Place, Beer, User, Photo, comments and junction tables, user backup tables, views, and various storage engines (MyISAM + InnoDB). This is no longer a single domain schema, but multiple generations of architecture living in the same database.
At the same time, the actual domain core of pivkarta.ru is much smaller. The data shows several thousand venues (Place ~3.8k), about 1.6k beer varieties/items Beer, ~13k PlaceBeer relations, photos, users, and relations between venues, beer, metro stations, and users; plus content entities like comments, topics, news/blogs, etc. Which of these are actually needed by the modern version of the product remains to be determined based on actual requirements—the number of records in itself does not prove that a feature needs to be migrated.
This clearly confirms the thesis from the article "MODX pays a huge ongoing architectural price for functionality that most projects barely use": even an empty table does not mean zero architectural cost. If a subsystem exists, working with legacy requires figuring out its model, relations, runtime semantics, and understanding whether it can be safely discarded. In this database, the effect is physically obvious: most of the schema describes engine capabilities and historical experiments rather than today's domain model of pivkarta.ru.
Changing the Direction of the Experiment
In the previous worklog, the first option was the minimally invasive path: keep the existing MySQL as the persistence boundary and connect the new API via Knex. After reviewing the schema, this option no longer looks obviously optimal.
Now, a more promising hypothesis is to create a new clean database with a minimal domain model and migrate only the provenly necessary data into it. Use the old database as a data source and requirements archaeology site, but do not make it the permanent foundation of the new architecture.
This adds work now: the agent will have to figure out which of the 250 tables actually participate in the product, which are MODX/Prisma/Extras technical tables, which represent old versions of the same data, and which features are no longer needed at all. But this is precisely what makes for a good HAIH brownfield test: do not carry over accumulated complexity just because it already exists; restore the real requirements and assemble a minimal new model for them.
The next logical step is to build a map of legacy tables → real capabilities → needed/not needed → new model → migration/verification, and then choose the first vertical scenario and migrate it along with data end-to-end.
Related experiment: haih.site and task /tasks/cmujk0ehv0m20qw0rs14y30bw. Current task: /tasks/cmqqxckd3003zp50up0dmzbld.