Building a Cloud Home Lab on a Budget: GCP and AWS Free Tier for Certification and Portfolio Work
How to set up a real cloud practice environment without a runaway bill — free tier limits, automatic shutdown strategies, what's worth running persistently vs. spinning up on demand, and what to build for actual portfolio signal.

Building a Cloud Home Lab on a Budget: GCP and AWS Free Tier for Certification and Portfolio Work
The advice to "build real projects to prepare for cloud certifications" is correct and almost universally given without guidance on how to do it without a surprise monthly bill. I've received a $340 AWS invoice because I forgot a NAT Gateway was running in an account I thought was empty. I've had GCP send me a billing alert at 11pm because a Dataflow job I left running consumed $90 of streaming processing credits in four hours.
A cloud home lab is not inherently cheap. The free tier is narrower than marketing suggests, and the transition from free to paid is fast for certain services. This guide is what I wish I had before my first learning account got expensive.
What the Free Tiers Actually Cover
Both GCP and AWS offer permanent free tiers (not just trial credits) for a subset of services. Understanding the difference between permanent free, 12-month free, and trial credits is foundational to keeping costs under control.
GCP Always Free
Google Cloud's Always Free tier is genuinely useful for a learning lab:
- Compute Engine — 1 e2-micro instance per month in specific US regions (us-east1, us-west1, us-central1). This is a real VM, permanently free. It's limited (2 vCPUs burstable, 1 GB RAM) but sufficient for running small services, learning IAM, experimenting with networking, and hosting a personal project.
- Cloud Storage — 5 GB of Regional storage, 1 GB egress per month to certain destinations. Enough for serving static assets, learning lifecycle policies, and testing access controls.
- Cloud Functions — 2 million invocations per month, plus compute and networking allowances. Sufficient for experimenting with serverless event-driven patterns.
- Firestore — 1 GB storage, 50,000 reads, 20,000 writes per day. Genuinely usable for a small application or API backend.
- BigQuery — 10 GB storage, 1 TB of queries per month free. The query limit sounds large; a single poorly-partitioned table scan on a medium dataset can consume it in minutes. Always preview query costs before running.
- Cloud Run — 2 million requests per month, 360,000 GB-seconds of compute. Enough to run a containerized application with moderate traffic for free.
GCP $300 Trial Credit
New GCP accounts receive $300 in free credits valid for 90 days. This is separate from Always Free and is where I recommend spending initial learning time — it allows you to run services that aren't in the Always Free tier (Cloud SQL, GKE, Spanner, Dataflow) without worrying about cost. Use it for certification lab work that requires managed databases and Kubernetes. The $300 goes further than you expect if you shut down resources when not in use.
AWS Free Tier
AWS splits its free tier into three categories:
- Always Free — Lambda (1 million requests/month), DynamoDB (25 GB storage, 25 read/write capacity units), SNS (1 million publishes), SES (62,000 outbound emails).
- 12 months free (from account creation) — EC2 t2.micro or t3.micro (750 hours/month), S3 (5 GB), RDS db.t2.micro or db.t3.micro (750 hours/month), CloudFront (1 TB data transfer/month).
- Trial — certain services offer 30–60 day trials of specific tiers (SageMaker, Redshift, etc.).
The 12-month EC2 free tier is useful for learning but expires. RDS in free tier is single-AZ and limited; it's fine for learning but not representative of production multi-AZ configurations.
Services That Will Surprise You With a Bill
Understanding which services generate unexpected costs is more important than memorizing free tier limits.
NAT Gateway — $0.045/hour per NAT Gateway plus $0.045/GB processed (AWS pricing). A NAT Gateway running 24/7 in a dev environment costs roughly $32/month before data transfer charges. I now never create NAT Gateways in personal accounts. For internet access from private subnets in lab environments, I either use a NAT instance (free, runs on EC2) or route through a public subnet temporarily.
Elastic IPs in AWS — free when attached to a running instance; $0.005/hour when unattached. A forgotten EIP (Elastic IP address) from a terminated instance costs $3.60/month. I run a monthly check for unattached EIPs.
RDS and Cloud SQL — even the smallest database instances cost $15–30/month when running continuously. I snapshot and delete databases after lab sessions rather than leaving them running.
Data transfer — both AWS and GCP charge for data leaving the cloud. High egress from a misconfigured application (or a public bucket being scraped) can generate significant bills. For learning accounts, I set billing alerts at $10 and $25.
Kubernetes clusters — GKE standard clusters charge per node. A 3-node e2-standard-2 cluster runs roughly $100/month. GKE Autopilot charges per pod resource request, which is more predictable but still nonzero. For learning Kubernetes, I run clusters for specific lab sessions and delete them after — a cluster running 4 hours/day for lab work costs a few dollars per month rather than $100.
Dataflow and BigQuery jobs — streaming Dataflow jobs are metered per CPU and memory second. A misconfigured streaming pipeline can consume $20–50 of credits in a few hours. Always test with batch jobs first; switch to streaming only when you understand the cost model.
The Billing Alert Setup I Run in Every Account
Before I run any experiment in any cloud account, I set up billing alerts. This takes five minutes and has saved me from significant unexpected charges multiple times.
GCP:
- Enable billing export to BigQuery (useful for analysis later)
- Set budget alerts: $10, $25, $50 with email notifications
- Optionally, set a budget action to disable billing at a threshold (nuclear option — it disables the project)
AWS:
- Enable Cost Explorer and Billing Alerts in the root account
- Create CloudWatch billing alarms: $10, $25, $50 thresholds
- Subscribe to AWS Health notifications for service interruptions that might affect running resources
I also use a Lambda function (in AWS) or Cloud Function (in GCP) that runs nightly and sends me a daily cost summary. It takes 30 minutes to set up and catches drift before it accumulates.
What to Actually Build for Portfolio Signal
The question isn't just "what can I afford to run?" but "what demonstrates meaningful architectural judgment to a technical interviewer or client?"
Effective portfolio projects are specific, documented, and solve a real problem — even a small one. Here's what I've built in my lab accounts that has generated the most client and interviewer interest:
A multi-tier application with proper IAM isolation — not just "I deployed an app to GCP/AWS" but a documented architecture where the frontend service cannot access the database directly, secrets are managed through Secret Manager or Secrets Manager (not environment variables), and the deployment pipeline uses service accounts with minimal permissions. This demonstrates IAM judgment, not just ability to deploy.
A cost-monitored infrastructure with automated reporting — the setup described above: billing alerts, nightly cost summary, tagging enforced by policy. Counterintuitive as portfolio work, but clients who have been burned by contractor-created cost overruns respond well to evidence that you've thought about this.
A disaster recovery runbook with tested recovery — document the recovery procedure for a simple application, then actually follow it: terminate the primary, recover from backup, measure RTO and RPO. The process of writing a runbook you've actually tested is different from one you've only theorized about, and interviewers who probe for this can tell the difference.
A CI/CD pipeline with rollback — not just deploying on merge, but a pipeline with smoke tests, canary deployment, and documented rollback procedure. GitHub Actions to Cloud Run or ECS, with a blue/green deployment and automated rollback trigger if health checks fail.
A security audit script — a script or workflow that checks a GCP project or AWS account for common misconfigurations: public S3 buckets, overly-permissive IAM policies, security groups with 0.0.0.0/0 ingress on sensitive ports, unencrypted EBS volumes. This demonstrates security-mindedness without requiring you to have built something large.
None of these projects require persistent running resources. Each can be built in a weekend, documented in a README, and kept as a codebase without ongoing cost.
My Lab Account Structure
I maintain separate accounts for different purposes:
GCP:
- One personal project on the Always Free tier — permanently running e2-micro, used for DNS experiments, small scripts, and persistent personal tooling
- One "learning" project — spun up for certification prep or specific service exploration, deleted when the learning session ends
- Billing alerts on both at $10 and $25
AWS:
- One personal account with billing alerts and Cost Explorer enabled
- No persistent compute running outside of free tier limits
- NAT Gateways never created (nat instance or public subnet for lab work)
- Monthly cleanup: check for unattached EIPs, orphaned snapshots, idle load balancers
This structure keeps my personal lab spend under $10/month most months, and never above $30 even during active certification preparation.
Infrastructure as Code for Everything, Even Experiments
One habit that separates lab work that builds real skill from lab work that doesn't: write Terraform (or CDK, or Pulumi) for every infrastructure component you create in a learning account, even throwaway experiments.
The reasons are practical:
- You can destroy and recreate the entire environment in minutes, eliminating persistent cost
- You catch misconfigurations in code review before they reach the cloud
- The repository becomes a reference library for real client work
- Terraform state documents exactly what is running, so nothing gets forgotten and left on
My lab repositories on GitHub are the most credible portfolio signal I have for infrastructure work. Not because they're impressive applications — most are small, single-purpose, and unremarkable in complexity — but because they show real architectural thinking: module structure, variable abstraction, clear outputs, documented assumptions.
A main.tf with 300 lines of hardcoded values in a single file is not portfolio material. A repository with a logical module structure, a backend configuration, documented variables with descriptions, and a README explaining the architecture tradeoffs is.
When to Stop Labbing and Start Billing
The risk with a well-maintained home lab is using it indefinitely as a substitute for client work. Certification preparation and skill development are legitimate uses of lab environments. But real infrastructure judgment develops through production constraints — deadlines, budget limits, stakeholder requirements, on-call incidents — that lab environments don't replicate.
The lab is for building vocabulary: learning what services exist, how they interact, and what their failure modes look like. Client work is where you develop architectural judgment about which services to use and why.
If you've been running a lab for six months and haven't converted that work into a paying engagement, the lab is probably not the bottleneck. The bottleneck is visibility (who knows about your skills), positioning (what kind of work you're presenting yourself for), and outreach (whether you're actively pursuing clients). No amount of additional lab work fixes a pipeline problem.
Resources
- GCP Always Free tier documentation
- AWS Free Tier details
- GCP Pricing Calculator
- AWS Pricing Calculator
- OpenCost — Kubernetes cost monitoring
- Infracost — Terraform cost estimation
Structuring Lab Work for Maximum Learning Return
Time in a cloud lab is only as valuable as the questions you're answering while you're in it. Unstructured lab time — "I'll just explore" — tends to produce familiarity with the console and shallow knowledge of many services. Structured lab time, organized around specific architectural decisions, produces the deeper understanding that transfers to production work and certification exams.
I structure lab sessions around decision trees rather than service demos. Instead of "let me deploy a Cloud Run service," the question is: "For a stateless API handling 1,000 requests per minute with a 200ms p95 latency requirement, when does Cloud Run make more economic sense than GKE, and what's the crossover point?" Answering that question requires deploying on both platforms, running load tests, checking the billing, and comparing — and the answer stays with you.
A decision tree I've worked through in lab that paid off in real client work:
When to use Pub/Sub vs. Cloud Tasks vs. Cloud Scheduler:
- Pub/Sub: fan-out messaging, multiple subscribers, event-driven architecture, at-least-once delivery
- Cloud Tasks: reliable task queue with exactly-once delivery semantics, HTTP target, explicit retry control
- Cloud Scheduler: cron-based job triggering, not a queue — no retry on application failure, no task history
Running all three in a lab to process the same simulated workload revealed a nuance I hadn't appreciated from documentation alone: Cloud Tasks has a significantly lower maximum throughput than Pub/Sub and is not appropriate for high-volume event streaming. That detail doesn't appear prominently in the comparative documentation but is exactly the kind of constraint that determines the right architecture for a client's use case.
The GitHub Repository Structure That Actually Signals Competence
Lab work that doesn't leave a visible artifact has limited portfolio value. The repository structure I've converged on for personal infrastructure projects:
project-name/
├── README.md # Problem statement, architecture, tradeoffs
├── modules/ # Reusable Terraform modules
│ ├── networking/
│ ├── compute/
│ └── iam/
├── environments/ # Environment-specific configurations
│ ├── dev/
│ └── prod/
├── docs/
│ ├── architecture.md # Why this design over alternatives
│ └── runbook.md # How to operate it
└── .github/
└── workflows/ # CI/CD pipeline definition
The README opens with the problem the infrastructure solves, not the technology it uses. The docs/architecture.md explains why Pub/Sub over Cloud Tasks, why Cloud Run over GKE, why this IAM structure over simpler alternatives. These decisions are what technical reviewers look for — not the specific services chosen, but evidence that the choices were made deliberately.
A repository in this structure, even for a small project, communicates infrastructure maturity more effectively than a larger project with a flat file structure and no documentation.
Related Articles
Kubernetes Cost Optimization: What I Actually Do on Production Clusters
11 min read
CareerForeign Income and Korean Tax: What Independent Contractors Working With US and EU Clients Need to Know
12 min read
CareerInfrastructure Documentation That Actually Gets Read: A Contractor's Approach
12 min read
Cloud Engineer · Part-time CS Lecturer · Seoul, South Korea · 5+ years infrastructure
I write about technical career management, variable income, and the performance habits that matter when you work independently — drawing on production infrastructure work and on teaching CS to students who won't accept hand-waving. Read full bio →
This article is for informational purposes only and does not constitute medical, legal, or financial advice.
Browse more articles