Actionable rules for designing, coding, deploying and operating cloud-agnostic microservices and infrastructure with Go, Kubernetes, Terraform and GitOps.
Finally escape the cloud provider trap with battle-tested patterns that let you deploy anywhere, migrate freely, and optimize costs automatically.
You've seen the horror stories. Companies spending months migrating off AWS because of unexpected cost spikes. Teams stuck rebuilding applications when Google Cloud deprecates yet another service. Engineers burning weekends trying to replicate production issues because their staging environment uses different cloud services.
The problem isn't using cloud providers – it's becoming dependent on them. Every proprietary SDK you integrate, every managed service you rely on, every vendor-specific API you call builds another bar in your cloud prison.
What if you could build once and deploy anywhere?
These Cursor Rules transform how you architect cloud applications. Instead of writing code that only works on one provider, you'll build truly portable systems using Go, Kubernetes, and infrastructure-as-code patterns that work identically across AWS, GCP, Azure, or even on-premises.
This isn't about avoiding the cloud – it's about using it on your terms.
Portable Application Architecture
Production-Ready Patterns
Workflow Automation
Stop second-guessing architectural decisions because you're afraid of vendor lock-in. Build with confidence knowing you can move workloads between providers in days, not months.
Before: 6-month migration project to move from AWS to GCP
After: Identical Terraform apply in new region, DNS cutover in 1 hour
Your team writes code once and deploys everywhere. No more maintaining separate implementations for different environments or clouds.
Concrete Example: Authentication service works identically in local Kind cluster, staging on GKE, production on EKS, and disaster recovery on AKS – same Docker image, same Helm chart, same configuration.
Built-in workload placement controllers read spot pricing APIs and automatically schedule non-critical workloads on the cheapest available resources across providers.
Real Impact: One team reduced compute costs by 40% by automatically shifting batch workloads between AWS spot instances and GCP preemptible VMs based on real-time pricing.
Reproduce production issues locally using the exact same container images and configurations. No more "works in staging but not production" mysteries caused by environment differences.
Your Git workflow becomes cloud-agnostic by default:
# Single commit triggers deployment to all environments
git push origin feature/user-auth
# CI runs identical pipeline steps:
# 1. Go tests with mocked cloud interfaces
# 2. Integration tests using localstack + kind
# 3. Helm chart deployment to any target cluster
# 4. Automated verification across all environments
The workload placement controller automatically optimizes your infrastructure spend:
# Your deployment yaml remains unchanged
apiVersion: apps/v1
kind: Deployment
metadata:
name: batch-processor
annotations:
scheduler.io/cost-optimized: "true"
scheduler.io/max-latency: "5m"
# Controller automatically selects cheapest nodes across regions
Recovery procedures become simple Terraform operations:
# Activate DR site with identical infrastructure
terraform apply -var-file=prod.tfvars -var region=us-west-2
# DNS cutover happens automatically via health checks
# RTO: 5 minutes, RPO: 30 seconds
Create the standardized layout that supports cloud-agnostic development:
your-service/
├── cmd/ # Application entrypoints
├── internal/ # Private application code
├── pkg/ # Public interfaces and shared code
├── api/ # OpenAPI specs and generated clients
├── deploy/ # Kubernetes manifests and Helm charts
├── terraform/ # Infrastructure modules
└── docs/adr/ # Architecture decision records
Set up dependency injection and interface-driven design:
// Define cloud-agnostic interfaces
type BlobStorage interface {
Upload(ctx context.Context, key string, data []byte) error
Download(ctx context.Context, key string) ([]byte, error)
}
// Inject implementations at runtime
func NewApp(storage BlobStorage, db Database) *App {
return &App{storage: storage, db: db}
}
Create Terraform modules that work across providers:
# modules/kubernetes-cluster/main.tf
variable "cloud_provider" {
description = "Target cloud provider"
type = string
validation {
condition = contains(["aws", "gcp", "azure"], var.cloud_provider)
error_message = "Provider must be aws, gcp, or azure."
}
}
# Single module, multiple provider implementations
Configure OpenTelemetry to work with any monitoring backend:
// Initialize tracing that works everywhere
tracer, err := otel.NewTracer(
otel.WithServiceName("your-service"),
otel.WithSpanExporter(jaeger.NewExporter(
jaeger.WithCollectorEndpoint(os.Getenv("JAEGER_ENDPOINT")),
)),
)
Ready to break free from cloud vendor lock-in? These Cursor Rules give you the patterns, practices, and tooling to build truly portable cloud applications. Your future self will thank you when the next cloud migration takes hours instead of months.
Copy these rules into your Cursor configuration and start building cloud-agnostic applications that deploy anywhere, migrate freely, and optimize costs automatically.
You are an expert in cloud-agnostic software and infrastructure: Go • Docker • Kubernetes • Helm • Terraform • Ansible • GitOps • Prometheus/Grafana • Datadog • Octopus Deploy.
Key Principles
- Prioritise portability: no vendor-specific SDKs or managed service lock-ins
- Everything is code: application, infrastructure, policy, docs
- Prefer open standards (OCI, CNCF, OPA, OpenTelemetry)
- Immutable, declarative resources; idempotent operations
- Twelve-Factor + microservices; loosely coupled, independently deployable
- Secure-by-design: defence-in-depth applied identically in every cloud
- Observability is mandatory: metrics, logs, traces published in open formats
- Fail fast & recover fast: health probes, auto-scaling, circuit breakers
- Cost & performance aware: right-size and dynamically shift workloads
Go
- Default to Go 1.22+ modules; use semantic import versioning (vX)
- Enforce `go vet`, `staticcheck`, `golangci-lint` in CI
- Project layout: `cmd/`, `internal/`, `pkg/`, `api/`, `deploy/`
- Use context.Context as the first param after receiver; cancel on timeouts
- Interface-driven design; depend on behaviour, not concrete cloud vendors
- Avoid global state; inject dependencies via constructors
- Return `(T, error)` not panics; errors wrap with `%w` and sentinel errors
- Logging: structured (zap, zerolog) with cloud-agnostic trace IDs
- Build flags: `-trimpath -ldflags "-s -w -X main.version=$TAG"`
Error Handling & Validation
- Validate config/env vars on start-up; exit non-zero on failure
- Treat external calls (DB, queue, HTTP) as unreliable; wrap in retry w/ back-off
- Check for transient vs permanent errors; expose retry-ability via error types
- Use early returns; keep happy path visually last (“guard clauses”)
- Surface user-safe messages; hide internal details behind correlation IDs
- Emit OpenTelemetry span events on every error path
Kubernetes (Framework-Specific)
- All manifests Helm-templated; values.yaml is the only mutable file
- Deployments stateless; state externalised (DB, message bus)
- Resource naming: <service>-<component>-<env> (e.g. auth-api-prod)
- Labels/annotations: `app.kubernetes.io/*` + `team`, `version`, `commit`
- Liveness vs readiness probes; 5s/10s defaults; maxUnavailable=1
- Requests equal to avg load; limits = 2× requests; never omit
- Secrets managed via ExternalSecrets or HashiCorp Vault injections
- Network policy: default deny; only open required ports (+ egress)
- HorizontalPodAutoscaler: CPU 70% OR custom `requests_per_second`
Terraform (Framework-Specific)
- Modules: one concern each, root module wires them
- Version every module; pin providers via `~>`
- Use `for_each` over `count` for clearer diffs and object meta
- Explicit outputs for cross-module references; no `data.*.id` lookups
- Remote state in backend cloud-agnostic (e.g. s3-compatible + Dynamo or GCS+Lock)
- Run `terraform fmt -recursive` and `tflint` in CI
- Protect prod with `prevent_destroy` and mandatory `-var-file=prod.tfvars`
Additional Sections
Testing & CI/CD
- Unit tests ≥90% critical pkg; mocks via Go interfaces, not real clouds
- Integration tests spin kind (K8s-in-Docker) + localstack/MinIO to mimic clouds
- e2e pipeline: Codefresh → Helm chart → Octopus Deploy to any target cloud
- GitOps: main branch merge triggers Argo CD sync; no kubectl manual apply
Observability
- Metrics via Prometheus client; histogram buckets pre-defined per SLO
- Logs shipped as JSON to stdout; collected by Fluent Bit; viewed in Grafana Loki
- Traces via OpenTelemetry gRPC exporter; sampling 5% in prod, 100% in staging
Security
- SCA & image scanning via Trivy in every build
- SBOM produced and published to registry (CycloneDX)
- OPA (Gatekeeper) policies: disallow privileged, hostNetwork, latest tag
- mTLS between services using cert-manager + Istio on-cluster; same config for all clouds
Performance & Cost Optimisation
- Autoscale via HPA/VPA; enable cluster-autoscaler
- Enable multi-region active-active when latency SLA > 150 ms
- Implement workload placement controller that reads spot/pricing API & taints nodes
Infrastructure Workflow
- Branch → PR → `terraform plan` comment → review → squash merge → `apply` via CI
- Disaster recovery: run `terraform apply` in alternate region daily (–target backup)
Documentation
- Every module/component owns a README with: purpose, inputs, outputs, examples
- ADRs stored in `/docs/adr/` with sequential numbering-date