Real-World Project - Building a Microservice

The Microservice That Survived Black Friday

It was 11:58 PM on Thanksgiving when our CTO sent the message: "We're expecting 10x traffic tomorrow. Are we ready?"

Our product catalog service was handling 500 requests per second normally. Black Friday would bring 5,000+ req/s. I spent that night stress-testing our Go microservice.

The Python version from last year had crashed at 800 req/s:

  • Out of memory after 2 hours

  • No graceful shutdown (interrupted orders)

  • No health checks (load balancer sent traffic to dying pods)

  • Manual restarts required

The Go rewrite was different:

// Health check endpoint
func (s *Server) healthHandler(w http.ResponseWriter, r *http.Request) {
    if !s.isHealthy() {
        w.WriteHeader(http.StatusServiceUnavailable)
        return
    }
    w.WriteHeader(http.StatusOK)
}

// Graceful shutdown
func (s *Server) Shutdown(ctx context.Context) error {
    log.Info("Shutting down gracefully...")
    return s.httpServer.Shutdown(ctx)
}

// Metrics endpoint
func (s *Server) metricsHandler(w http.ResponseWriter, r *http.Request) {
    promhttp.Handler().ServeHTTP(w, r)
}

Black Friday results:

  • Peak: 7,200 req/s (40% above estimate)

  • Uptime: 100% (zero restarts)

  • Memory: 180MB stable (no leaks)

  • Response time: 23ms p99 (under load)

  • Revenue: $1.2M processed without issue

That night taught me: production-ready isn't just working code. This article covers building microservices that survive real traffic.


Project Structure


Building the HTTP Server

Server Setup

internal/server/server.go:


Graceful Shutdown

cmd/server/main.go:

Why graceful shutdown matters:

  • Finishes in-flight requests

  • Closes database connections

  • Flushes logs and metrics

  • Prevents data corruption


Health Checks and Readiness Probes

Health Check

Simple liveness check - is the service running?

Readiness Check

Deeper check - is the service ready to handle traffic?


Metrics with Prometheus

Setup Prometheus

Define Metrics

internal/middleware/metrics.go:

Expose Metrics

Access metrics:


Structured Logging

pkg/logger/logger.go:

internal/middleware/logging.go:

Output:


Docker Containerization

Multi-Stage Dockerfile

deployments/Dockerfile:

Build and run:

Benefits of multi-stage build:

  • Builder image: 800MB (has Go compiler)

  • Final image: 15MB (only binary + Alpine)

  • Faster deployment, less attack surface


Kubernetes Deployment

Deployment

deployments/kubernetes/deployment.yaml:

Service

deployments/kubernetes/service.yaml:

Deploy to Kubernetes


Complete Working Example

internal/product/model.go:

internal/product/handler.go:


Makefile for Development


Your Challenge

Build a complete TODO API microservice:


Key Takeaways

  1. Graceful shutdown: Finish in-flight requests before stopping

  2. Health checks: Liveness and readiness probes

  3. Metrics: Prometheus for monitoring

  4. Structured logging: JSON logs for observability

  5. Multi-stage Docker: Small, secure images

  6. Kubernetes: Production-grade orchestration

  7. Resource limits: Prevent memory/CPU runaway

  8. Middleware: Logging, metrics, recovery


What I Learned

That Black Friday microservice taught me production-ready means more than working code:

  • Graceful shutdown prevented corrupted orders during deployments

  • Health checks ensured traffic only went to healthy pods

  • Metrics showed bottlenecks before they became incidents

  • 7,200 req/s handled smoothly, 40% above estimates

  • $1.2M revenue processed with 100% uptime

Coming from Python microservices that needed 4GB and struggled with concurrency, Go's efficiency was transformative. The service runs on 180MB RAM and handles more traffic than we ever expected.

Two years later, it's still the most reliable service we have. Zero production incidents. Zero manual restarts.

The confidence to sleep through Black Friday? Priceless.


Congratulations! 🎉

You've completed the Go 101 series! You've learned:

  1. Go basics and why it's different

  2. Functions, methods, and error handling

  3. Data structures and memory management

  4. Structs, interfaces, and composition

  5. Error handling philosophy

  6. Concurrency with goroutines and channels

  7. Advanced concurrency patterns

  8. Package management with modules

  9. Testing and TDD

  10. JSON and REST APIs

  11. Database operations

  12. Best practices and code organization

  13. Building CLI tools

  14. Building production microservices

Where to go next:

  • Build real projects

  • Contribute to open source

  • Read "Effective Go" and "Go Proverbs"

  • Join the Go community

  • Keep learning and shipping

Welcome to the Go community. Now go build something amazing! 🚀

Last updated