Migrating 200 Microservices from Jenkins to GitHub Actions in 3 Months
👤 @platform_peteSaaS100-500 engineers2025
01The Setup
Our platform team managed a Jenkins cluster running over 200 pipelines for our microservices. Jenkins was running on a fleet of 40 EC2 instances, costing us roughly $25k/month in compute alone. We had 3 full-time engineers maintaining the Jenkins infrastructure, dealing with plugin updates, security patches, and flaky executors. Build times averaged 18 minutes and teams were constantly complaining about queue times during peak hours.
02What Happened
After a particularly bad week where Jenkins was down for 6 hours due to a corrupted plugin update, leadership approved the migration to GitHub Actions. We formed a 4-person migration squad. The biggest challenge was that each of the 200 pipelines had its own quirks — custom Groovy scripts, shared libraries, artifact caching patterns, and deployment hooks. We built a transpiler that converted 80% of Jenkinsfile syntax to GitHub Actions YAML, then manually handled the remaining 20%. We migrated in waves of 20-30 services, starting with the least critical.
03Timeline
Week 1-2: Built the Jenkinsfile-to-Actions transpiler
Week 3-4: Migrated 30 internal tools and low-risk services
Week 5-8: Migrated 120 mid-tier services in 4 waves
Week 9-11: Migrated 50 critical-path services with parallel running
Week 12: Decommissioned Jenkins cluster
04The Resolution
The migration was completed in 11 weeks, one week ahead of schedule. Build times dropped from 18 minutes to 7 minutes average thanks to better caching and parallelism. Monthly CI/CD costs dropped from $25k to $12k. We eliminated the 3-person Jenkins maintenance burden. The transpiler we built was open-sourced and got 400 GitHub stars in the first month.
LessonsWhat We Learned
01
When migrating CI/CD systems, invest in automation tooling upfront — the transpiler paid for itself 10x over.
02
Run old and new pipelines in parallel for critical services before cutting over.
03
Start migration with the hardest cases to find edge cases early, not the easiest ones for quick wins.
What I'd Do Differently
We should have started with the most complex pipelines first, not the simplest. The easy ones gave us false confidence — the hard ones had edge cases that required changes to our transpiler, which then needed to be re-run against already-migrated services.