AdTech · AWS migration
Revenue infrastructure for a global AdTech platform.
From legacy to cloud-native in 12 months.
A newly formed team inherited grown PHP legacy code running revenue reporting for a global AdTech platform with nine-figure turnover. The brief: modernize it and migrate it into a scalable AWS environment while it keeps running. Timeline: 12 months.

The starting point
New team. Old code. No safety net.
A newly formed team was spun out of an existing large team and took over responsibility for the PHP legacy code behind revenue reporting. The code was running in production, but it had grown over years: no test coverage, no documented infrastructure, no infrastructure as code.
Revenue feeds from external partners were imported and normalized daily, campaign reports delivered to internal teams and external partners. The system had to deliver correct data every day, in an environment where mistakes have immediate business consequences. Every change was a risk because nobody knew what it would trigger.
The challenge
Modernizing while it keeps running.
No test coverage means no safety. Every change to the legacy code was a blind flight. Incidents happened regularly, the causes were hard to find, the fixes risky.
At the same time there was no infrastructure as code. The AWS infrastructure was configured manually, undocumented, not reproducible. What ran in the cloud was known only to the person who had set it up. The task was to modernize the system, migrate it to PHP 8, move it into a clean AWS environment and deliver correct revenue data every day at the same time. Twelve months, live operations, no downtime allowed.
My approach
Understand.
Secure.
Migrate.
Understand and secure the codebase
Analysed the legacy code and built test coverage from 0 to over 90%. PHPUnit for unit tests, Codeception for acceptance tests that lock down the system behaviour towards external partners. Only once changes are safe can you modernize.
PHP 8 migration
Migrated the entire legacy code to PHP 8, including reworking every outdated component. Modernized Symfony as the framework base. Step by step, controlled, with test coverage as a safety net.
Cloud migration to AWS
Migration into a scalable AWS environment: ECS for containerized services, EC2 for compute-intensive workloads, SQS and SNS for asynchronous processing, RDS for relational data, Athena and Glue for analytical queries and data transformation. The entire infrastructure as code in Terraform, versioned and reproducible. Nothing configured manually any more.
Estimates per click calculation for media buyers
Built the estimates-per-click calculation as a standalone service. The values are calculated daily and provided as an export so media buyers can optimize their campaigns based on data. Push budget into high-performing channels, cut back weak ones. A direct connection between technical infrastructure and measurable business outcome.
Data availability through AWS DataZone
Revenue data is made available internally to every department through AWS DataZone. No more distributing reports by hand, no data silo. Every department has access to the data it needs.
Legacy code with no tests, no IaC and regular incidents?
Find out in a few minutes how high your risk really is.
What was hard
Protecting against systems you do not own.
Testing against third party systems. The revenue feeds came from external partners, and that boundary is exactly where the errors appear: a field that suddenly stays empty, an amount with a different decimal separator, a timezone that shifts with daylight saving. You cannot test against other people’s production systems, and their sandboxes do not reproduce those cases.
The answer was acceptance tests that pin down the system behaviour at that boundary: recorded real feeds as the basis, plus the failure cases that had already occurred in operation. That did not cover every future case, but it covered every past one. Enough to touch the code underneath without guessing with every change.
The rest was a matter of attitude: anything coming from outside is treated as potentially wrong. An import that fails loudly on bad data beats one that quietly processes it. In revenue reporting a wrong number otherwise surfaces when a partner disputes it.
The outcome
More stable. Faster. Available to everyone.
Incidents
Test coverage from 0 to over 90% explains why incidents dropped by 90%.
Test coverage
PHPUnit for unit tests, Codeception for acceptance tests: the system behaviour is fully locked down.
Infrastructure as Code
The entire AWS infrastructure in Terraform: versioned, reproducible, no more manual clicking.
Grown PHP legacy code with no tests, no documented infrastructure and regular incidents, moved into a modern, stable AWS environment. Test coverage from 0 to over 90% explains why incidents dropped by 90%. The infrastructure is fully versioned as code. Estimates-per-click values are calculated daily and available to media buyers for campaign optimization. Revenue data is available to every department through AWS DataZone. A modernization while it kept running, in a nine-figure turnover environment, without a single day of downtime.
Technologies used
Proven tools. No experiments.
- Golang
- gRPC
- Symfony
- PHP 8
- AWS ECS
- EC2
- SQS
- SNS
- RDS
- Athena
- Glue
- DataZone
- DynamoDB
- S3
- IAM
- Terraform
- Docker
- OpenTelemetry
- Datadog
- Grafana
- CloudWatch
- PHPUnit
- Codeception
- Testcontainers
Client voices
What clients say.
“A big thank you to Tim! The AWS migration was a really big chunk for us, but you handled it with complete confidence. Especially with the small issues that came up along the way, you were on it immediately and did not let go until everything ran.”
Frequently asked
What clients ask before deciding.
How do you migrate nine-figure revenue reporting without downtime?
Step by step, with a way back for every step. First infrastructure as code for the target environment, then reconciliation between old and new, then redirecting individual reports. Only after both sides produced identical numbers for weeks was the old path switched off.
Where did 90 percent fewer incidents come from?
From three sources: test coverage above 90 percent where money moves; reproducible environments instead of hand-maintained servers; and monitoring that notices problems before customers do. The causes were rarely exotic, they were simply invisible before.
What happens to the knowledge after twelve months?
It stays with the team. That was part of the brief: a newly formed team should not only inherit the code but be able to develop it. Hence pairing rather than delivery, and documented decisions rather than a final report.
