🚀 Migration

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.