Case study
Moving a live Formula 1 ticketing platform out of a disrupted AWS region
A Formula 1 circuit, via Browser London. Contract. 2025–2026. Sole engineer on the migration and the new stack.
Client context
The client is a Formula 1 circuit. Its public site has two parts. One is a WordPress marketing site in English and Arabic. The other is a custom PHP ticketing application on the AudienceView ticketing API. The ticketing app has no database of its own. It turns web requests into ticketing API calls and renders the results.
The region went down
In March 2026 strikes on AWS facilities disrupted the Bahrain region (me-south-1). The platform's whole AWS estate ran there. I moved it to Ireland (eu-west-1) over March and April 2026. I did all of the migration myself. No S3 buckets were lost in the move.
Why it needed a new stack anyway
The old platform ran one PHP 7.4 container as six ECS tasks on EC2. PHP 7.4 reached end of life in November 2022. In August 2026 a routine media plugin update required PHP 8.1. It broke every image on the site. The tasks and the load balancer stayed healthy, so no health check caught it. I rolled the image back. The runtime was now blocking routine security updates. The stack could no longer be maintained without being changed.
The new architecture
I re-architected the platform on Amazon ECS with AWS Fargate.
- Two services: the CMS and the ticketing app. A WordPress plugin update can no longer take ticketing offline. Each service scales on its own.
- WordPress on Bedrock. Core and every plugin are pinned with Composer. A plugin update is now a one-line, reviewable change.
- PHP 8.3 and a major WordPress upgrade.
- Configuration from SSM Parameter Store. No secrets in the repository.
- Amazon ElastiCache for Valkey holds sessions and cache.
- Amazon RDS for the CMS database. Media in S3, served through CloudFront.
- CloudFront and AWS WAF in front. The load balancer accepts traffic only from CloudFront.
- Cutover by Application Load Balancer rule. Rollback takes seconds. The old platform stayed in place as a rollback target.
The main site moved to the new stack in August 2026. I recorded each design decision as an architecture decision record.
Delivery and observability
I rebuilt CI/CD on Bitbucket Pipelines. Each image is built once. OIDC to AWS replaced a static access key. Every production deploy waits for a manual approval. I wrote the deploy and rollback runbooks.
I built the observability layer in CloudWatch: structured JSON logs, metric filters, alarms, and a dashboard. The definitions live in the repository.
The August 2026 on-sale
In August 2026 the platform sold tickets for a Formula 1 race weekend. I ran production through the on-sale.
- The day before launch, the database saturated for 14 minutes. I traced it to a single scanning IP address. It was making thousands of requests for missing pages, and each one ran uncached. I tightened the WAF rules. I locked the load balancer so it accepts traffic only from CloudFront. I replaced long-lived AWS keys with task roles.
- I found and fixed several classes of server error. The largest single fix cut server errors by about 85 percent.
- I load-tested with k6. The ceiling was about 11 requests per second at the ticketing vendor's API. Our containers were not the limit.
- I pre-staged a Queue-it waiting room as a Lambda@Edge connector. Turning it on is one reversible CloudFront change. It needs no software release.
- I found a session-cookie defect. Our client code cut the vendor's session cookie short by 17 characters. About two thirds of ticketing calls failed as a result. After the fix, pricing calls went from 3 of 8 succeeding to 10 of 10.
The September 2026 on-sale
On 30 September 2026 tickets for the next Formula 1 season went on sale on the new stack. A Queue-it waiting room was live for the event. Card payments had been stalling after the 3-D Secure device check. The 3-D Secure provider had moved that check to a new host. Our page only trusted the old one. I fixed it before the sale. On the day I shipped a card-form hotfix. Form rejections fell from 82 of 88 submits to 0 of 5.
How I work on it
I operate the platform with an AI coding agent (Claude Code) under written guardrails I authored. Nothing deploys straight to production. Changes go to UAT first. AWS profile rules are fixed. No secrets go in config. Decisions live in ADRs. Procedures live in runbooks.
Stack
- Amazon ECS
- AWS Fargate
- ALB
- CloudFront
- AWS WAF
- Lambda@Edge
- RDS
- S3
- ElastiCache (Valkey)
- SSM Parameter Store
- CloudWatch
- IAM OIDC
- Docker
- Bitbucket Pipelines
- k6
- WordPress
- Bedrock
- Composer
- PHP 8.3
- WPML
- AudienceView API
- Queue-it