Legacy modernization for startups and SMBs, before support runs out
We upgrade aging Django, Python and cloud infrastructure before it falls out of support, without a risky rewrite. Tests go in first, then the upgrade, then a cutover you can roll back, with slow pages and cloud cost fixed along the way.
Deadlines That Are Already Here
Most support windows for the stack Django products run on close in 2026. Past these dates, security fixes stop, and on AWS some of them start costing extra.
Django 4.2 LTS
Security support ended: April 2026
New Django vulnerabilities are no longer patched on 4.2. Django 5.2 LTS is supported until April 2028, so it is the natural target.
Python 3.10
End of life: October 2026
Python 3.9 already ended in October 2025. Python 3.11 reaches end of life in October 2027, so a one-step upgrade buys only a year.
Node.js 20
End of life: April 2026
Frontends, build tooling and server code on Node.js 20 now run on a release line that no longer gets upstream security fixes.
Amazon Linux 2
End of support: June 2026
Servers and machine images still on Amazon Linux 2 no longer receive security updates and need moving to a supported operating system.
Amazon RDS for MySQL 8.0
End of standard support: July 2026
Instances still on MySQL 8.0 move to paid RDS Extended Support. Upgrading to a supported engine version avoids that charge.
Leaving Heroku or Another Platform?
Moving off a platform you have outgrown follows the same path: tests first, a staged move, and a cutover you can roll back.
Cloud Migration & DevOpsModernization & Upgrade Services
From a single Django version bump to moving a whole product off an aging platform, with the test coverage that makes each step safe.
Django & Python Upgrades
Move Django 4.2 or older to 5.2 LTS and Python to a supported release, one version step at a time, fixing deprecations as we go.
- Django 5.2 LTS and supported Python
- Dependency and deprecation cleanup
- Replacements for abandoned packages
Test Coverage First
Most aging codebases have thin tests. We add tests around the paths that matter before touching versions, so every step is checked.
- Tests on critical user flows
- CI that blocks regressions
- Coverage gaps mapped to risk
Cloud Platform & Runtime Upgrades
Move servers off Amazon Linux 2, runtimes off Node.js 20, and databases onto supported engine versions, testing your app on each new platform first.
- OS and machine image upgrades
- Node.js and container base images
- Amazon RDS engine version upgrades
Database Migration
Move off an old database or engine version with rehearsed migrations and data checks before and after, so you can prove nothing was lost.
- MySQL or Oracle to PostgreSQL
- Major engine version upgrades
- Data integrity validation
Upgrading a Django codebase specifically? See Django Modernization. Changing clouds or leaving a platform? See Cloud Migration & DevOps. Planning AI next? Data stuck behind an unsupported database or old framework is the usual blocker, so modernizing first gives AI Agents in Production something solid to build on.
Cost and Speed Review
An upgrade already touches every layer, so we fix performance and cloud spend in the same pass instead of selling it as a separate project. It is part of every Upgrade Assessment.
Slow Pages and Queries
We profile the slowest endpoints and fix the usual causes: N+1 queries, missing indexes, and work that should be cached.
Core Web Vitals
We measure LCP, INP and CLS on your real pages and fix what drags them down: heavy assets, blocking scripts and slow server responses.
Right-Sizing and Idle Resources
We find oversized instances, forgotten environments, and orphaned volumes and snapshots, then resize or remove them.
LLM and Inference Cost
For teams already running AI features: caching repeated requests, routing simple calls to smaller models, and tracking cost per request.
Upgrade, Migrate, Rescue, or Rebuild?
The honest version of the trade-off. Most systems need the smallest change that removes the risk, not a rewrite.
Upgrade in place (what we usually recommend)
Keeps the business logic that already works and removes the support and security risk underneath it.
Needs a test safety net first. Skipping the tests is where most upgrades break.
Pick when the product still fits the business but the stack under it is aging.
Phased migration
Moves off an aging framework, database or platform in stages, with users served throughout.
Old and new run side by side for a while, which takes careful routing and data sync.
Pick when the platform itself has to change, not just its versions.
Rescue first
Stabilizes an inherited or failing system before any big decision is made.
It is triage, not the end state. An upgrade or migration usually follows.
Pick when incidents, missing docs or a departed team make any change unsafe.
Rebuild
A clean foundation when the architecture cannot support where the business is going.
Full rewrites take longer than planned and freeze feature work while they run.
Pick only when repair clearly costs more than replacement and the business case is clear.
How We Upgrade Without a Rewrite
The order of work is the safety: tests first, then the upgrade, then a cutover you can roll back.
Audit Versions and Risk
We check every framework, runtime, package and service against its end-of-life date, and map where the tests are thin.
Tests First
We add tests around the critical paths and wire them into CI, so each upgrade step is checked before it ships.
Upgrade in Stages
We move one version step at a time, fixing deprecations and replacing dead packages, instead of one big-bang jump.
Rehearsed Cutover
We rehearse the data migration and cutover in staging, ship with a tested rollback, and watch production closely afterward.
Start With an Upgrade Assessment
A fixed-scope first step that shows what is out of support, what the upgrade will take, and where your cloud bill and slow pages can be fixed, before you commit to the work.
Upgrade Assessment
A clear picture of what you run, what is past or near end of life, and the safest order to fix it.
- Version, dependency and end-of-life audit
- An upgrade path with test gaps and risks called out
- A cost and speed review of your cloud bill and slowest pages
Upgrade & Cutover
Upgrade in stages behind a test safety net, then switch over with a plan you have already rehearsed.
- Tests in place before any change
- Staged upgrade, one version at a time
- Rehearsed cutover with rollback
Run & Improve
Stay current so you never face a cliff-edge upgrade again.
- Versions kept current
- Security patches applied promptly
- Monitoring, with cloud cost tracked
Modernization Technology Stack
The systems we most often upgrade and migrate, and the tooling we use to keep every step tested.
Frameworks & Runtimes
- Django 5.2 LTS
- Python (supported releases)
- FastAPI & Celery
- Node.js for frontends & tooling
Data & Storage
- PostgreSQL & Amazon RDS
- MySQL / Oracle to PostgreSQL
- Redis
- Elasticsearch
Cloud, CI & Testing
- AWS / GCP
- Docker
- GitHub Actions CI
- pytest & coverage
Selected Work
Django platforms we have built for clients and for ourselves.
BottleCRM
Self-hosted CRM platform for startups and SMBs, combining CRM workflows, invoicing, support, multi-tenant architecture, and full-stack product delivery.
FireMatters
Fire safety compliance platform for Australian building owners with automated service regime calculations, asset tracking, and document workflows.
NowFinance
Loan advisor portal with affiliate network management, dynamic dashboards, and workflow support for financial consultants.
Frequently Asked Questions
Straight answers to what founders and CTOs ask us before an upgrade or migration.
What is legacy modernization?
Legacy modernization is upgrading the frameworks, runtimes, databases and infrastructure under an existing product so it stays supported, secure and fast, without rebuilding it from scratch. In practice that means version upgrades, dependency cleanup, database and platform migrations, and fixing performance and cloud cost along the way, usually in stages so the product keeps running throughout.
Is it safe to keep running Django 4.2 or Python 3.10 after end of life?
Not for long. Django 4.2 LTS stopped receiving security fixes in April 2026 and Python 3.10 reaches end of life in October 2026, so any vulnerability found after those dates stays open in your stack. The app keeps running, but the packages you depend on gradually drop support for old releases, which makes every later upgrade harder. Plan the move now: Django 5.2 LTS is supported until April 2028.
What if we are on Amazon Linux 2 or Amazon RDS for MySQL 8.0?
Plan the move now. Amazon Linux 2 reached end of support in June 2026, and Amazon RDS for MySQL 8.0 reached the end of standard support in July 2026, after which instances still on it move to paid Extended Support. We upgrade the operating system, machine images and database engine versions in stages, testing your application on the new platform before switching traffic.
What does an Upgrade Assessment include?
It is a fixed-scope first step with three parts. We audit every framework, runtime and dependency against its end-of-life date, lay out an upgrade path that calls out where tests are missing and where the risks sit, and review your cloud bill and slowest pages for cost and speed fixes. You come away with a written plan and a fixed estimate for the upgrade, so you can decide what to do and in what order before committing to the work.
How do you upgrade without disrupting users?
By keeping each change small and reversible. Tests go in first so regressions are caught before release, the upgrade ships in stages rather than as one big switch, and the data migration and cutover are rehearsed in staging with a tested rollback plan. Most steps ship like any normal release. Where a cutover needs a maintenance window, we schedule it for your quietest hours and keep it as short as possible.
Can you fix performance and cloud cost as part of modernization?
Yes. The upgrade already touches every layer, so it is the right moment, and the Upgrade Assessment includes a cost and speed review. We profile slow pages and queries (N+1 queries, missing indexes, missing caching), check Core Web Vitals, and look for oversized or idle cloud resources. For teams already running AI features, we also cut LLM and inference cost with caching and model routing.
Do you use AI tools to upgrade code?
Yes, for the mechanical work. AI-assisted tooling speeds up syntax changes, deprecation fixes and first drafts of tests, and an engineer reviews every change. Our engineers own the parts where upgrades actually fail: test coverage, data migration and the cutover itself. AI makes the repetitive work faster; it does not decide what is safe to ship.
How long does a Django or Python upgrade take?
It depends on scope: how many versions you are behind, how many third-party packages need replacing, and how much test coverage exists today. A small app one LTS release behind is a very different job from a large codebase several versions back with thin tests. The Upgrade Assessment answers this for your system, and you get a fixed estimate for the upgrade after it.
Do we own the code?
Yes. You own all source code, tests, infrastructure configuration and documentation we produce. Everything is committed to your repositories as we work, with no lock-in, so you can run, extend or bring the work in-house at any time.
Upgrade Before the Deadline, Not After
Tell us what you run (Django and Python versions, hosting, database). We will tell you honestly what is at risk, what can wait, and the safest order to upgrade it.