From legacy constraints to GitOps-enabled microservices: A journey with AWS ECS and Fargate
Author: Javad Zeynal | November 9, 2024
Abstract
When stepping into a new project, it’s not uncommon to inherit infrastructure that "just works" — until it doesn’t. In one of my recent consulting projects, our team took over a customer’s legacy AWS environment that followed a widely used microservices pattern. The initial setup looked reasonable, but it quickly became clear that modernization was not just optional — it was essential.
A familiar architecture with hidden constraints
At the heart of the platform was a typical AWS stack: requests from the outside world hit an Amazon API Gateway, which routed traffic through a VPC Link to a private Network Load Balancer (NLB). From there, the NLB directed traffic to an ECS cluster running on Fargate, where multiple microservices were deployed. The system also incorporated Amazon RDS for relational data, Amazon S3 for object storage, and AWS Lambda functions triggered via SQS queues for asynchronous tasks.
While this architecture followed established patterns, it hid a significant architectural limitation: all five microservices were deployed together in a single ECS task definition. Every time a developer made a change to just one service — a bug fix, a new feature, a configuration tweak — the entire group of services had to be redeployed.

This setup undermined many of the promises of microservices architecture. It prevented independent deployments, delayed release cycles, and increased the risk of production issues due to unnecessary redeployments. It also meant that services which should scale independently were tightly coupled in their lifecycle.

Decoupling the architecture
My first step was to untangle this monolith-by-deployment. I split the single task definition into five independent ECS services, each with its own task definition, target group, scaling configuration, and deployment pipeline. This brought immediate benefits: faster deployments, more granular rollback options, and true service-level isolation.
The improved architecture also enhanced resilience. Services could now scale independently based on demand, and infrastructure issues could be debugged and resolved without taking down unrelated parts of the system.

A new challenge: monolithic pipelines
With infrastructure decoupled, attention shifted to the development lifecycle. Despite the improved runtime separation, the CI/CD process still treated the codebase as a monolith. All five services lived in a single repository, and every change triggered a pipeline that built, tagged, and pushed all container images to Amazon ECR — regardless of which service had actually changed.
This was inefficient and expensive, both in terms of compute usage and developer time.

Implementing GitOps for scalable delivery
To solve this, I introduced a GitOps-style approach. Each microservice was given its own logical boundary within the repository. The CI/CD pipeline was redesigned to detect changes at ...

Want to learn more?

If you're working with a legacy ECS system, struggling with deployment bottlenecks, or curious about applying GitOps principles in your cloud environment — I’d be happy to share more. The right architectural improvements don’t always require starting over. Sometimes, they just require the right plan.
NAVIGATION
HELP
Datenschutzerklärung
Impressum
Copyright © 2025
BAQUE Solutions
Made on
Tilda