I recently worked on a DevOps project with a simple starting point: an application that worked perfectly fine on my local machine.
The application, LibraryCorner, consists of a frontend, a FastAPI backend, and a PostgreSQL database. It was already containerized with Docker, so technically, everything worked.
But “it works on my machine” is very different from running a service in a production-like environment.
So I gave myself a challenge:
How can I transform a local application into a service that is deployable, highly available, observable, and recoverable?
These four properties became the foundation of the project.
The Architecture
I deployed the application on AWS using EKS for container orchestration and RDS PostgreSQL for the database.
The request flow looks roughly like this:
User → Route 53 → Application Load Balancer → EKS → RDS PostgreSQL
The EKS nodes and the database run inside private subnets, while the Application Load Balancer acts as the public entry point.
Around this core architecture, I used:
- Terraform for Infrastructure as Code
- GitLab CI/CD for automation
- ECR for Docker images
- AWS Secrets Manager for secrets
- Prometheus & Grafana for monitoring
- CloudWatch for AWS monitoring
- S3 for Terraform state
I also separated the development and production environments, each with its own infrastructure.
1. Deployable
My first goal was to avoid manual infrastructure changes as much as possible.
The AWS infrastructure is managed with Terraform, while the application deployment is handled through GitLab CI/CD.
The pipeline builds the Docker images, pushes them to ECR, and deploys the application to Kubernetes.
For AWS authentication, I used OIDC instead of storing long-lived AWS access keys in GitLab.
I actually wrote a separate article about this because I found the authentication flow particularly interesting.
2. Highly Available
Deploying something to Kubernetes doesn't automatically make it highly available.
I configured the EKS infrastructure across multiple Availability Zones and deployed multiple application replicas.
An Application Load Balancer distributes incoming traffic, while Kubernetes can replace unhealthy pods.
I also configured a Horizontal Pod Autoscaler (HPA) to scale the application between 2 and 6 pods depending on resource usage.
For the production database, RDS uses a Multi-AZ configuration.
The idea is simple: the application shouldn't depend on a single instance, pod, or Availability Zone.
3. Observable
A service can be running and still be unhealthy.
That's why monitoring was another important part of the project.
I used Prometheus to collect Kubernetes and application metrics and Grafana to visualize them.
This gave me visibility into things like resource usage, pod health, and application behavior.
I also configured alerts so that important problems don't require someone to constantly watch a dashboard.
This part of the project changed the way I think about infrastructure: deploying an application is only the beginning. You also need to understand what happens after deployment.
4. Recoverable
High availability doesn't replace backups.
I wanted to know what would happen if the database actually had to be restored.
So instead of simply enabling RDS snapshots and assuming recovery would work, I performed a real restoration test.
The measured recovery time was approximately 14 minutes.
For me, this was one of the most useful exercises in the project because it turned disaster recovery from a configuration checkbox into something measurable.
What I Learned
The biggest lesson wasn't about a specific AWS service.
It was understanding how all these pieces work together.
Terraform creates the infrastructure. GitLab automates delivery. Kubernetes manages the workloads. AWS provides the underlying services. Prometheus and Grafana tell me what's happening. Backups give me a recovery path when things go wrong.
And each layer introduces its own decisions and trade-offs.
This project also reminded me of something from my QA background:
A system isn't reliable because we expect it to work. It's reliable because we can verify what happens when it doesn't.
What's Next?
This article was an overview of the architecture, but several parts deserve their own deep dive.
Next, I'll share how I built the AWS EKS infrastructure with Terraform, including some of the problems I encountered and what I learned while fixing them.
If you're also learning AWS, Kubernetes, or DevOps by building projects, I'd love to hear about what you're working on.
Top comments (0)