A Global, Managed, and High-Performance backend infrastructure for hosting multiplayer game servers on AWS. Built with Terraform (IaC), Amazon GameLift Container Fleets (managed game server hosting), and CI/CD automation via GitHub Actions.
Note: This is a portfolio/demo project. The game server simulates player connections and state management to demonstrate the full infrastructure stack working end-to-end.
Key Components:
| Layer | Components |
|---|---|
| Deployment Pipeline | GitHub → GitHub Actions → Build Docker → Push to ECR → Update GameLift Fleet |
| Networking | VPC with public/private subnets across 2 AZs, NLB for game traffic |
| Compute | Amazon GameLift Container Fleets (On-Demand, managed placement) |
| Storage | S3 (versioned game assets), DynamoDB (player state + leaderboard) |
| Container Registry | Amazon ECR (game server + init container images) |
multiplayer-game-server-aws/
├── terraform/ # Infrastructure as Code
│ ├── modules/
│ │ ├── vpc/ # VPC, subnets, NAT, IGW, GameLift SG
│ │ ├── gamelift/ # Container Fleet, Container Group, IAM, scaling
│ │ ├── ecr/ # Container registries
│ │ ├── s3/ # Game asset storage
│ │ └── dynamodb/ # Player state database
│ ├── environments/
│ │ ├── dev/ # Dev environment (1 instance, c5.large)
│ │ └── prod/ # Prod environment (2+ instances, c5.xlarge)
│ └── backend.tf # S3 + DynamoDB state backend
├── gamelift/ # GameLift Container Definitions
│ ├── container-group-definition.json
│ ├── fleet-config-dev.json
│ └── fleet-config-prod.json
├── game-server/ # Demo game server application
│ ├── src/server.js # Node.js UDP/TCP/HTTP server
│ ├── Dockerfile # Multi-stage production build
│ └── init-container/ # S3 asset sync container
├── .github/workflows/
│ ├── ci.yaml # PR checks: lint, validate, plan, build
│ └── cd.yaml # Deploy: build, push ECR, update GameLift
└── README.md
| Tool | Version | Install |
|---|---|---|
| AWS CLI | v2+ | Install Guide |
| Terraform | v1.10+ | Install Guide |
| Docker | v24+ | Install Guide |
# Create S3 bucket for Terraform state
aws s3api create-bucket \
--bucket game-server-terraform-state \
--region eu-west-2 \
--create-bucket-configuration LocationConstraint=eu-west-2
# Enable versioning on the state bucket
aws s3api put-bucket-versioning \
--bucket game-server-terraform-state \
--versioning-configuration Status=Enabled
# Create DynamoDB table for state locking
aws dynamodb create-table \
--table-name terraform-state-lock \
--attribute-definitions AttributeName=LockID,AttributeType=S \
--key-schema AttributeName=LockID,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--region eu-west-2cd terraform/environments/dev
terraform init
terraform plan -var-file=terraform.tfvars
terraform apply -var-file=terraform.tfvars# Login to ECR
aws ecr get-login-password --region eu-west-2 | \
docker login --username AWS --password-stdin \
$(terraform output -raw game_server_ecr_url | cut -d/ -f1)
# Build and push game server
docker build -t game-server ./game-server
docker tag game-server:latest $(terraform output -raw game_server_ecr_url):latest
docker push $(terraform output -raw game_server_ecr_url):latest
# Build and push init container
docker build -t game-server-init ./game-server/init-container
docker tag game-server-init:latest $(terraform output -raw game_server_init_ecr_url):latest
docker push $(terraform output -raw game_server_init_ecr_url):latest# Check fleet status
aws gamelift describe-container-fleet \
--fleet-id $(terraform output -raw gamelift_fleet_id) \
--region eu-west-2
# List fleet instances
aws gamelift describe-instances \
--fleet-id $(terraform output -raw gamelift_fleet_id) \
--region eu-west-2Modular infrastructure with 5 reusable modules. Each environment (dev/prod) composes the same modules with different variables.
Key design decisions:
- GameLift Container Fleets — managed game server hosting, no cluster ops overhead
- On-Demand instances — predictable performance, no Spot interruptions during game sessions
- Single NAT Gateway — saves ~$32/month vs one per AZ
- On-demand DynamoDB — PAY_PER_REQUEST billing eliminates capacity planning
A Node.js demo server exercising the full AWS stack:
- UDP 7777 — Simulated real-time game traffic
- TCP 7778 — Player connection lifecycle (connect → load state → play → save state → disconnect)
- HTTP 8080 — Health checks + Prometheus-ready metrics endpoint
Container group definitions (replaces Kubernetes manifests):
- Init container syncs game assets from S3 before the game starts
- Game server container with health checks and environment configuration
- Dev fleet: 1 instance, c5.large, no session protection
- Prod fleet: 2-10 instances, c5.xlarge, auto-scaling, full session protection
- CI (on PR): Terraform lint/validate/plan, Docker build, GameLift JSON validation
- CD (on merge): Build → Push to ECR → Update Container Group Definition → Update Fleet
| Resource | Estimated Monthly Cost | Notes |
|---|---|---|
| GameLift (1x c5.large On-Demand) | ~$62 | Includes GameLift management fee |
| NAT Gateway | ~$32 + data | Single NAT for cost optimization |
| DynamoDB | ~$0-5 | On-demand, pay per request |
| S3 | ~$1-5 | Depends on asset size |
| ECR | ~$1-3 | $0.10/GB/month |
| NLB | ~$16 + data | Per AZ-hour + LCU |
| Total (Dev) | ~$115-125/month |
Tip: Destroy dev environments when not in use:
terraform destroy -var-file=terraform.tfvars
cd terraform/environments/dev
terraform destroy -var-file=terraform.tfvars
# (Optional) Remove the state backend
aws s3 rb s3://game-server-terraform-state --force
aws dynamodb delete-table --table-name terraform-state-lock| Secret | Description |
|---|---|
AWS_ACCESS_KEY_ID |
IAM user access key (or use OIDC federation) |
AWS_SECRET_ACCESS_KEY |
IAM user secret key |
AWS_ACCOUNT_ID |
Your 12-digit AWS account ID |
Recommended: Replace static credentials with GitHub OIDC Federation for production use.
- GameLift FlexMatch — Automatic player matchmaking
- Monitoring — CloudWatch dashboards + Prometheus/Grafana
- CloudFront CDN — Cache and deliver game assets globally
- AWS WAF — DDoS protection for game traffic
- Multi-region fleets — Deploy across regions for low-latency global access
- GameLift Queues — Multi-fleet placement for optimal latency
| Category | Technology |
|---|---|
| Cloud Provider | AWS (VPC, GameLift, ECR, S3, DynamoDB, NLB) |
| Infrastructure as Code | Terraform ~> 5.0 |
| Game Server Hosting | Amazon GameLift Container Fleets (On-Demand) |
| Container Runtime | Docker (multi-stage builds) |
| CI/CD | GitHub Actions |
| Application | Node.js 20 + AWS SDK v3 |
| State Management | DynamoDB (on-demand) |
| Asset Storage | S3 (versioned, encrypted) |
| Region | eu-west-2 (London) |
This project is licensed under the MIT License.
