Case Study

GitOps on AWS EKS: Deploying ClassKira's Multi-Tenant SaaS LMS

Updated July 2026 10 Min Read
Kubernetes EKS Container Orchestration
Deploying multi-tenant architectures requires robust pipelines, zero-downtime rollouts, and secure OIDC integration.

Scaling a modern Software-as-a-Service (SaaS) application requires balancing resource efficiency with strict security. In the educational sector, this challenge is amplified. Educational platforms experience massive spikes in traffic during active class hours and exam periods, followed by complete silence at night. Furthermore, schools and universities demand absolute data isolation—no student or administrator should ever see data belonging to another institution.

This case study dissects the architectural design and deployment flow of classkira.com, a leading multi-tenant Learning Management System (LMS) SaaS. We will explore how it utilizes a database-per-tenant architecture, runs efficiently on AWS Elastic Kubernetes Service (EKS), secures connections via GitHub OIDC, and automates continuous deployments using GitOps with Argo CD.

Understanding Multi-Tenant LMS SaaS

In a single-tenant architecture, each customer gets their own separate server and database. While secure, this is incredibly expensive to maintain and update. In contrast, multi-tenancy allows multiple customers (called "tenants") to share the same computing infrastructure, drastically reducing operational costs.

For ClassKira, multi-tenancy is structured around a "Shared Compute, Isolated Data" model:

  • Subdomain Routing: Each school receives a custom subdomain (e.g., academy.classkira.com, school-a.classkira.com).
  • Shared Application Pool: All incoming requests hit the same pool of Laravel containers running inside AWS EKS, avoiding the overhead of maintaining individual servers for every academy.
  • Dynamic Database Routing: At the application level, a custom Laravel middleware identifies the tenant based on the incoming subdomain host header. It instantly switches the active database connection to that specific tenant's dedicated database schema (Database-per-Tenant model).

ClassKira Multi-Tenant Dynamic Database Routing

School A school-a.classkira.com
School B school-b.classkira.com
School C school-c.classkira.com
ALB & Tenant Middleware
Parses subdomain Host header & dynamically sets active connection string.
db_school_a Isolated Schema
db_school_b Isolated Schema
db_school_c Isolated Schema
Why Database-per-Tenant? "While a shared database with a tenant_id column is easier to set up, it carries a higher risk of data leakage due to programmer bugs. By using isolated database schemas, ClassKira guarantees that an SQL injection or coding error in one tenant's portal can never leak data from another."

Why AWS EKS and GitOps?

Deploying updates in a multi-tenant environment is high-stakes. A single broken deployment doesn't just affect one user; it can instantly halt operations for hundreds of schools, locking thousands of teachers and students out of classrooms.

To mitigate this risk, ClassKira relies on AWS Elastic Kubernetes Service (EKS) coupled with a strict GitOps continuous delivery pipeline:

  1. Infrastructure elasticity: Kubernetes allows ClassKira to scale container pods up in seconds during peak morning logins, and scale them down to a minimum configuration overnight to save costs.
  2. Declarative State: With GitOps, the desired state of the EKS cluster is fully written out in YAML manifest files inside a Git repository. We don't log into servers to run commands. Git is the single source of truth.
  3. Continuous Reconciliation: Argo CD runs inside EKS, continuously comparing the live cluster state with the declared files in Git. If someone manually alters a setting in EKS, Argo CD immediately detects the drift and overrides it back to the Git-defined configuration.

Securing the Cloud Handshake: OIDC & STS

Traditional CI/CD pipelines require storing long-lived credentials (like AWS_ACCESS_KEY_ID) in GitHub secrets. If a developer account or repository is compromised, those credentials can leak, giving hackers administrative access to the entire AWS account.

ClassKira solves this using OpenID Connect (OIDC) and AWS STS (Security Token Service) to implement a passwordless, short-lived trust relationship:

OIDC Token Exchange Process
1. Runner Job Workflow starts on temporary runner VM.
2. JWT Token Runner requests identity token from GitHub.
3. IAM Trust AWS IAM trusts GitHub repository identity.
4. AWS STS Exchanges JWT for temporary credentials.
5. ECR Access Runner pushes Docker image to ECR securely.

Because the generated credentials expire automatically after a short period (typically 1 hour), there are no permanent keys to be stolen, making the system incredibly resilient to credential leaks.

The CI/CD Code Deployment Flow

From a developer committing code to a live update in production, the ClassKira pipeline operates as a fully automated conveyor belt. Let's trace the steps of a code change:

CI/CD & GitOps Loop
GitHub Commit Code

A developer merges their code changes or bug fixes to the main branch.

Actions Trigger Pipeline

GitHub Actions detects the push event and launches the pipeline workflow.

Runner Build & Test

A temporary VM boots up, runs tests, and packages the app into a container.

composer install php artisan test docker build -t app:sha .
ECR Push Image

Runner authenticates via OIDC and pushes the tagged Docker image to ECR.

Git Update Manifest

Workflow commits the new image tag back to the Kubernetes deployment YAML file in GitHub.

Argo CD Sync Cluster

Argo CD detects the manifest change in Git, reconciles, and applies it to EKS.

EKS Pull Image

EKS worker nodes pull the new container image from ECR to spin up new pods.

Pod Rolling Update

New pods undergo health checks. Once active, old pods are terminated with zero downtime.

Disaster Recovery: The Rollback Strategy

No matter how thoroughly code is tested, production failures can happen—especially in a high-stakes multi-tenant environment. When a regression slips through, the priority is minimizing the Mean Time to Recovery (MTTR). In a GitOps architecture, rolling back changes is safe, structured, and auditable.

ClassKira uses a two-tier rollback strategy depending on the severity of the failure:

1. The GitOps-Native Rollback (Preferred Strategy)

Because Git is the source of truth, the cleanest way to roll back is to declare the rollback in Git. If a buggy deployment is detected, engineers perform a Git revert on the manifest repository:

Reverting Git State: git revert <commit-sha> && git push origin main

Once this revert commit is pushed to the main branch, Argo CD detects the drift (the image tag reverts to the previous version) and automatically triggers EKS to perform a rolling downgrade. EKS spins up the old stable pods and terminates the buggy ones, resolving the incident in under a minute.

2. The "Break-Glass" Emergency Rollback

If Git is temporarily inaccessible, or if the pipeline is blocked and every second counts to prevent downtime, engineers bypass the pipeline for immediate recovery:

  • Step A: Disable Argo CD Auto-Sync: Engineers pause Argo CD's auto-sync setting using the CLI or dashboard. This prevents Argo CD from fighting manual intervention and trying to re-apply the buggy Git configuration.
  • Step B: Rollback via Kubernetes: Run the native Kubernetes rollout command to instantly switch the deployment back to the previous revision:
    kubectl rollout undo deployment/classkira-app
    This directs EKS to immediately stop the buggy pods and spin the previous healthy replica set back up.
  • Step C: Resolve and Re-enable Sync: Once the system is stable, engineers diagnose the issue, push a clean fix to Git, and re-enable Argo CD auto-sync to let the standard pipeline resume control.

Runtime Traffic Flow & Auto-scaling

When teachers, students, and parents open ClassKira, their browsers establish connections directly to the production cluster. Here is the step-by-step route internet traffic takes:

End User Access Path
1
End User Requests A teacher opens schoolname.classkira.com in their browser.
2
DNS Resolution Route 53 resolves the domain request and forwards it to the Application Load Balancer (ALB).
3
AWS ALB & Ingress ALB terminates HTTPS, inspects host headers, and routes traffic through the Kubernetes Ingress controller.
4
Kubernetes Service Distributes requests among the list of healthy application pods inside the EKS cluster.
5
Laravel Application Pods Pods process requests, load tenant configurations, read/write isolated database data, and return HTML/JSON.

How ClassKira Dynamic Auto-Scaling Works:

  • Pod Auto-scaling (HPA): The Kubernetes Horizontal Pod Autoscaler (HPA) watches the CPU/Memory utilization of ClassKira pods. If usage crosses 70%, HPA commands EKS to scale up pod counts (e.g., from 3 to 10 replicas).
  • Node Auto-scaling (Karpenter): If the EKS cluster lacks the CPU/Memory capacity to schedule these new pods, Karpenter acts immediately, provisioning new EC2 instances in less than 30 seconds and joining them to the cluster.
  • Shrinking Capacity: As traffic drops in the evening, the reverse process occurs. Karpenter terminates idle EC2 instances and EKS deletes unused pods, ensuring ClassKira only pays for what it actually uses.
ClassKira User Traffic & EKS Architecture Map
User requests
school-a.com
school-b.com
Routing & DNS
Route 53
AWS ALB
AWS EKS Cluster
Ingress Controller
Laravel Pod Pool
Isolated Data
db_school_a
db_school_b
Open Interactive Flow Simulator

Full-Scale Production GitOps & EKS Architecture

For a production-grade multi-tenant SaaS, the infrastructure must be partitioned across several secure, scalable tiers. Below is the interactive blueprint representing ClassKira's full-scale architecture. Toggle between the tabs to explore the Infrastructure Blueprint, follow the Code-to-Cloud GitOps Pipeline, or deep-dive into the Multi-Tenant Data Isolation design.

Production Console

Active Cluster
Code & Delivery
Git Workspace Developer Env
GitHub Actions CI Pipeline
AWS ECR Container Registry
Edge & Gateway
AWS Route 53 Global DNS
AWS ALB Load Balancer
Ingress Controller Nginx Ingress
EKS Compute
Laravel Pod Pool App Runtime
Argo CD GitOps Controller
Karpenter Node Autoscaling
Data & Secrets
RDS Aurora PG Tenant DB Pool
ElastiCache Redis Cache & Queues
Secrets Manager AWS Secrets
Git Workspace Active
Developer Environment
Developers work in a local workspace, committing configuration changes to Helm/Kustomize charts and application code. All configurations are tracked in Git.
Git Localhost YAML manifests
1
Developer Push Git merge triggers CI workflow
2
GitHub Actions & OIDC Short-lived trust exchange
3
Build & Push to ECR Securely pushing artifacts
4
Manifest Update Auto-committing the new image tag
5
Argo CD Reconciliation Continuous cluster state sync
ci-workflow.yml
YAML
on:
  push:
    branches: [ main ]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Run PHPUnit Tests
        run: php artisan test
School A User school-a.classkira.com
Subdomain routing
db_school_a Isolated PostgreSQL Schema
School B User school-b.classkira.com
Subdomain routing
db_school_b Isolated PostgreSQL Schema
Laravel Pod (IRSA) IAM Role for Service Account
OIDC credential fetch
Secrets Manager AWS Secrets Storage

Conclusion: Key Architectural Lessons

ClassKira's EKS GitOps deployment strategy showcases the maturity of modern cloud-native systems. By separating concerns—using GitHub Actions strictly to build/test, and Argo CD to enforce EKS state—the platform gains stability and auditability. Combined with temporary OIDC token exchanges and strict database-per-tenant isolation, ClassKira delivers a highly secure, reliable, and cost-effective LMS SaaS for educational organizations worldwide.

Live Sandbox

Build Your Own GitOps Pipeline!

Tired of reading theory? Connect to our live interactive sandbox. You can set up a GitHub Actions workflow, configure OIDC permissions, build Docker containers, and sync manifests using Argo CD on a real, temporary Kubernetes cluster right from your browser.

100% Free & Interactive for Growth School Community No AWS Account or Local Setup Required Guided walkthroughs with instant feedback
Access EKS Live Lab
student@growthschool:~/argocd

argocd app create classkira --repo github.com/classkira --path k8s --dest https://kubernetes.default.svc

Creating application 'classkira'...

Application 'classkira' created successfully.

argocd app sync classkira

Cluster synced. 8 pods running.