How to Build Golang Microservices with Echo Framework?

Learn to build Golang microservices with Echo, creating Product and Order service, handling CRUD APIs, inter-service communication, and Docker Compose setup.

 Build Golang Microservices with Echo Framework

If you want to split your app into microservices but don’t want to overcomplicate things, this guide is for you. I’ll walk through how to build simple, clean microservices using Go and Echo, a lightweight and super fast web framework. We’ll use Docker Compose for containerization so you can run everything locally.

By the end of this, you’ll have two basic services: one for products, one for orders. They’ll talk to each other, handle versioned CRUD APIs, and be easy to run, test, and grow later.

What are Microservices?

Microservices are small, independently deployable services, each responsible for a single business capability. Unlike monolithic applications, microservices facilitate easier scaling, independent deployments, fault isolation, and faster iterations. 

Microservices architecture has rapidly become an industry standard for building scalable, maintainable, and highly resilient applications.

Why Go and Echo for Microservices?

Go Language (Golang), known for its simplicity, blazing performance, and powerful concurrency model, is an ideal choice for implementing microservices. Coupled with Echo, a high-performance and minimalist Go web framework, developers can build efficient, clean, and scalable RESTful APIs with minimal overhead.

7 Steps to Build Microservices in Go with Echo

Step 1: Set Up the Project

Let’s create the project folder and set things up:

mkdir microservices-echo
        cd microservices-echo
        go mod init github.com/yourusername/microservices-echo
        go get github.com/labstack/echo/v4

 

Step 2: Organize the Files

We’ll split it into two service

microservices-echo
    ├── product-service
    │   └── cmd
    │       └── main.go
    └── order-service
        └── cmd
            └── main.go

 

Step 3: Build the Product Service (CRUD + Versioning)

This service handles product data. It can create, update, fetch, and delete a product. And we’ll version the API from the start (so we can improve it later without breaking stuff).

Endpoints:

  • GET /api/v1/products/:id - Retrieves product details.
  • POST /api/v1/products - Creates a new product.
  • PUT /api/v1/products/:id - Updates an existing product.
  • DELETE /api/v1/products/:id - Deletes a product.
package main
    import (
    	"net/http"
    	"github.com/labstack/echo/v4"
    )
    func main() {
    	e := echo.New()
    	v1 := e.Group("/api/v1")
    	v1.GET("/products/:id", getProduct)
    	v1.POST("/products", createProduct)
    	v1.PUT("/products/:id", updateProduct)
    	v1.DELETE("/products/:id", deleteProduct)
    	e.Logger.Fatal(e.Start(":8081"))
    }
    func getProduct(c echo.Context) error {
    	id := c.Param("id")
    	return c.JSON(http.StatusOK, map[string]interface{}{"product_id": id, "name": "Product Name", "inventory": 100})
    }
    func createProduct(c echo.Context) error {
    	return c.JSON(http.StatusCreated, map[string]string{"status": "product created"})
    }
    func updateProduct(c echo.Context) error {
    	id := c.Param("id")
    	return c.JSON(http.StatusOK, map[string]string{"status": "product updated", "product_id": id})
    }
    func deleteProduct(c echo.Context) error {
    	id := c.Param("id")
    	return c.JSON(http.StatusOK, map[string]string{"status": "product deleted", "product_id": id})
    }

 

Step 4: Build the Order Service (Talks to Product Service)

Now let’s make the Order Service. When someone places an order, it checks with the Product Service and updates the inventory.

Endpoints:

  • POST /api/v1/orders - Creates a new order and updates product inventory.
package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"github.com/labstack/echo/v4"
)

func main() {
	e := echo.New()

	v1 := e.Group("/api/v1")
	v1.POST("/orders", createOrder)

	e.Logger.Fatal(e.Start(":8082"))
}

type OrderRequest struct {
	ProductID string `json:"product_id"`
	Quantity  int    `json:"quantity"`
}

func createOrder(c echo.Context) error {
	order := new(OrderRequest)
	if err := c.Bind(order); err != nil {
		return c.JSON(http.StatusBadRequest, err)
	}

	resp, err := http.Get(fmt.Sprintf("http://product-service:8081/api/v1/products/%s", order.ProductID))
	if err != nil {
		return c.JSON(http.StatusInternalServerError, err)
	}
	defer resp.Body.Close()
	body, _ := ioutil.ReadAll(resp.Body)

	inventoryUpdate := map[string]int{"inventory": -order.Quantity}
	updateBody, _ := json.Marshal(inventoryUpdate)
	_, err = http.Post(fmt.Sprintf("http://product-service:8081/api/v1/products/%s", order.ProductID), "application/json", bytes.NewBuffer(updateBody))
	if err != nil {
		return c.JSON(http.StatusInternalServerError, err)
	}

	return c.JSON(http.StatusOK, map[string]interface{}{
		"order_status": "created",
		"product_details": json.RawMessage(body),
	})
}

Step 5: Docker Compose Setup

We’ll use Docker Compose to spin up both services with one command: docker-compose.yml. Put this at the project root:

version: '3.8'
services:
  product-service:
    build: ./product-service
    ports:
      - "8081:8081"
  order-service:
    build: ./order-service
    ports:
      - "8082:8082"
    depends_on:
      - product-service

Each service will need a Dockerfile:

FROM golang:1.21-alpine

WORKDIR /app
COPY . .
RUN go mod tidy
RUN go build -o main ./cmd/main.go

EXPOSE 8081
CMD ["./main"]

For Order Service, change EXPOSE to 8082.

Step 6: Run Everything

Time to see it in action:

docker-compose up --build

Now both services are live.

Step 7: Test Communication

Use this curl command to test placing an order:

curl -X POST -H "Content-Type: application/json" -d '{"product_id": "123", "quantity": 5}' http://localhost:8082/api/v1/orders

You get something like this back:

{
	"order_status": "created",
	"product_details": {"product_id": "123", "name": "Product Name", "inventory": "100"}
}

Conclusion

That’s it! You now have two basic microservices built in Go with Echo, communicating with each other and running in Docker. It’s a solid starting point if you’re learning microservices or just want to build something small and clean.

From here, you can:

  • Add a real database
  • Improve error handling
  • Use a service discovery tool
  • Add auth or API gateway
  • Deploy to the cloud

But for now, you’ve got the foundation set. Keep building, keep learning — and most importantly, keep it simple.

>>> Follow and Contact Relia Software for more information!

  • golang
  • coding
  • web development