Hybrid CI/CD Strategy Overview

From CodePipeline to GitHub Actions: Our Hybrid Approach to CI/CD on AWS

At my last company, we were deep into AWS. Everything — from infrastructure to pipelines — was written as code using AWS CDK. While AWS offers some seriously powerful infrastructure, let's be honest: tools like CodeCommit, CodeBuild and CodePipeline aren't exactly known for their developer experience. Functional? Sure. Luxurious? Not so much.

At my current startup, we had a new challenge. We needed to:

  • Deploy to AWS (including EKS)
  • List our platform on AWS Marketplace
  • Maintain high confidence in our CI/CD pipeline
  • Enjoy a better developer experience than what AWS native tools alone could offer

So we decided to take a hybrid approach: keep using AWS where it shines (infrastructure and delivery), but move our CI to GitHub Actions, where the developer experience is best-in-class.

Why GitHub Actions for CI?

GitHub Actions gave us an instant productivity boost. We used it to:

  • Run unit tests and lint checks
  • Validate formatting
  • Perform security scans
  • Automate build validations before merging to main

All our continuous integration logic lived in GitHub. It was fast, transparent, and integrated seamlessly into our developer workflows.

Continuous Delivery in AWS — with a Handshake

Once our CI passed, we needed to hand off the result to AWS for deployment. There are many ways to do this — but we wanted something simple and effective. Here's what we did:

  1. Created a release S3 bucket in AWS
  2. Configured GitHub Actions to trigger on release tags
  3. Built our Kubernetes OCI images in GitHub Actions
  4. Saved them as tarballs
  5. Uploaded the release artifacts (& our CDK source) to S3 (as a single zip file, this made the trigger event simple)

This S3 bucket became our handoff point between GitHub CI and AWS CD.

AWS CDK-Powered Delivery Pipeline

On the AWS side, we leaned on CDK to manage our entire continuous delivery pipeline. Here's how it works:

  1. A new object in the release bucket triggers CodePipeline
  2. The pipeline:
    • Synthesizes CDK
    • Self-mutates infrastructure if needed (CDK deploy)
    • Pushes OCI tarballs to AWS ECR (with image scanning enabled)
    • Deploys to EKS using a Helm umbrella chart
    • (In production) Publishes the new version to AWS Marketplace

This hybrid architecture gives us the best of both worlds: great CI with GitHub Actions, and AWS-native CD that leverages our existing expertise and infrastructure.

Why Not Just Do Everything in GitHub?

We could have. GitHub Actions supports running CDK commands like cdk synth and cdk deploy, and you can use OIDC to grant GitHub secure access to your AWS accounts.

But that comes with added complexity: setting up IAM roles, trust policies, and ensuring secure, reliable access between GitHub and AWS. It's absolutely possible — and worth it at scale — but not necessarily the right starting point for every team.

Our goal was speed and confidence. So we took a pragmatic route: start with a hybrid handoff model and defer full GitHub-native CD until later.

Recommendation: Start Hybrid, Then Decide To Go Full GitHub

If you're currently all-in on AWS native CI/CD but looking to modernize, here's what I recommend:

  1. Move your source to GitHub and your CI to GitHub Actions. Get all your test/build/validate logic running there.
  2. Keep CD in AWS, but create a clear handoff — like an S3 bucket.
  3. Use CDK to wire up a CodePipeline that picks up your artifacts and deploys to EKS (or wherever).
  4. Once that's stable, decide if it's worth the extra effort to bring delivery into GitHub too.

That hybrid handoff — CI in GitHub, CD in AWS — is a sweet spot. You can always move further into GitHub later, but even this middle ground delivers massive value fast.

Final Thoughts

CI/CD is all about confidence and speed. With this hybrid approach, we optimized both — enjoying the rich developer experience of GitHub Actions while maintaining the deep integration and control of AWS-native delivery.

If you're considering a similar migration: start hybrid. Keep it simple, deliver value, and evolve your pipeline from there.