AI case studies
"It's working, so don't touch it." A system said to be off-limits like that, before anyone realized it, was still running at the center of the company as it was 10 years ago — many companies will recognize this. This time, we migrated a project-management system released in 2016 from a state where it wasstill exposed to the internet on top of an OS that reached end-of-support in 2020and in use, to a modern environment. Two working days.We carried over 3,623 tickets and 4.0 GB of attachments without a single loss.
"It's working, so we can't touch it" had gone on for 10 years.
The target was the company's project-management system (Redmine). Project progress, incident-response records, the history of exchanges with customers — 10 years of it had accumulated here. It was precisely a state ofcan't touch it because it can't be stopped.
But when we examined the contents, it was by no means a state that should be left alone.
| Item | Before migration | After migration |
|---|---|---|
| OS | CentOS 6.10 (end-of-support in 2020) | AlmaLinux 10.1 |
| Application | Redmine 3.2.1 (2016) | Redmine 6.1.3 |
| Runtime environment | Ruby 2.2.4 | Ruby 3.3.10 |
| Database | MySQL 5.7 | MariaDB 10.11 |
| Web server | Apache 2.2 + Passenger | nginx 1.26 + puma |
6 years since the OS went out of support.Not a single fix for the vulnerabilities disclosed in that time had been applied. And it kept running in a state accessible from outside the company. Not "safe because it's working," but rather,"merely working, but not protected"is the accurate way to put it.
It's that, without breaking, only the defenses have stopped.
The success of the migration was decided by measurements taken before starting.
Before beginning the migration, we pinned down the current state in numbers. This, as it turned out, greatly influenced the effort required.
- Database 38 MB / attachments 4.0 GB
- 20–30 requests per day =actively in use
- Extension plugins: zero. Custom design: none
That last line was decisive. What causes the most trouble in this kind of migration iswhether the extensions added later will work on the new version. If they don't, you're left with three choices — "find a replacement," "give up the feature," or "fix it yourself" — and weeks vanish there. This time, that obstacle didn't exist from the start.
Based on these measurements, we settled on three policies before starting.
1. We stopped upgrading one version at a time
Initially we estimated on the assumption of stepping up gradually, 3.2 → 4.2 → 5.1 → 6.x. But when we tested it, we found that we couldjump over 10 years' worth in one go and update directly. The effort we had assumed became entirely unnecessary.
2. We did not change the database product
There was a plan to move to a different database product to align operations with other systems. But because the source data format differs, that would require inserting a conversion step.We chose not to bring the risk of conversion into "data that's hard to notice if it disappears" — 3,623 tickets and 6,071 history entries.We prioritized not losing a single record over unifying operations.
3. We did not upgrade the existing server directly
We prepared a separate new server and made the switchover just a matter of rewriting one line of the entry-point configuration.If it fails, revert one line and it's back to normal — to maintain that state right to the end.
What ate up the time was not Redmine.
Here's where the real work is. Lining up the problems we hit during the migration, a clear pattern emerged.
Of the eight,only three stemmed from Redmine itself. And one of those was a pleasant miscalculation — "easier than expected." In practice, only two gave us any real trouble.
The rest were generational differences in the OS, the security mechanism, the communication path, encryption, and integration with external systems —all of them outside the application.
It's the "differences in the surrounding environment" built up over 10 years.
Never let go of "revertible in one line" until the very end.
The switchover is just pointing the entry-point server's forwarding destination at the new server. Reverting is also one line. Andwe left the old environment running rather than shutting it down.
On switchover day, a "running old environment" and a "running new environment" coexisted, and we kept a state where we could move between either with one line. After leaving it for a few days and confirming there were no problems, we shut down the old side.
We didn't stop at migrating; we filled in 10 years' worth of gaps.
In the new environment, we simultaneously put in place what the old environment lacked.
- Daily backups (7 generations) — the old environment had no backup mechanism at all
- Recording the source of access — before migration, all access looked identical, and there was no way to trace who was coming from where
- Limiting login attempts — since there's no standard feature, reinforced on the web-server side
- Automatic updating of the source-code integration — an integration that had effectively been frozen now updates every 15 minutes
The data we carried over is as follows. We confirmed that the counts match exactly between the old and new environments.
Integration from external systems also works as-is, with no configuration changes.From the users' point of view, only the login screen got a new look — an ideal landing for a migration.
If "we have the same kind of server too."
The reasons this migration finished in such a short time come down to three.
- There were no extensions installed — that's why we could jump over 10 years at once
- We measured before starting — the basis for decisions was laid out in numbers
- We kept it revertible — we didn't have to gamble on switchover day
Put another way,all three of these can be confirmed before you start."A system that can't be stopped is running on an end-of-support server." If that rings a bell, start by talking to us about grasping the current state in numbers. Whether it can be migrated can usually be determined by investigating.
We help you migrate and modernize business systems that keep running on end-of-support OSes and old frameworks.
A survey of the current state (version, data volume, presence of extensions, exposure) is free. Together with legacy system modernization (the AI Re: Platform / AIR Platform for short),Get in touch today.
Contact form(please add a note saying "Requesting a consultation on legacy migration") / info@flagship-ai.jp
Series: "Legacy to AI — Field Reports"
- Overview: 22 systems and 246,000 lines on a single PC — a measured record of 3.5 months of AI development
- Field Report ①: Fully modernizing 20-year-old Java in about a week
- Field Report ②: Adding a new entry point to a core system with zero lines of existing code changed
- Field Report ③: A month-scale architecture study, done with a 2-day prototype + real measurements
- Field Report ④: An old mining PC becomes an in-house "private ChatGPT" in two days
- Field Report ⑤: Rescuing a 10-year-old system off an end-of-support server in two days (this article)
* The figures in this article are measured values as of August 2026. The time required and the work involved in a migration vary depending on the system's configuration and whether extensions are present.