GoMicro - Go Microservices Architecture
Production-Ready Microservices with Kong Gateway & NATS

A complete microservices implementation using GoServe framework, Kong API Gateway, NATS messaging, PostgreSQL, MongoDB, and Redis.
Overview
This project demonstrates a production-ready microservices architecture built with the GoServe framework. It breaks down a monolithic blogging platform into independent services using Kong as API Gateway and NATS for inter-service communication. Each service maintains its own database and cache, showcasing true microservices best practices with service isolation, independent scaling, and fault tolerance.
The architecture implements authentication, authorization, and API key validation across distributed services while maintaining clean separation of concerns and independent deployability.
Features
- GoServe Micro Framework - Built on production-ready GoServe v2 with microservices support
- Kong API Gateway - Single entry point with custom Go plugin for API key validation
- NATS Messaging - Asynchronous inter-service communication with request/reply patterns
- Service Isolation - Each service with dedicated database and Redis instance
- PostgreSQL & MongoDB - Auth service with PostgreSQL, Blog service with MongoDB
- JWT Authentication - Token-based authentication with refresh token support
- Role-Based Authorization - Fine-grained access control across services
- Custom Kong Plugin - Go-based API key validation plugin
- Docker Compose Ready - Multiple configurations for development, testing, and production
- Load Balancing - Pre-configured setup for horizontal scaling
- Health Checks - Service health monitoring and dependency management
- Auto Migrations - Database schema migrations on startup
- Development Tools - pgAdmin, Mongo Express, Redis Commander included
Technology Stack
| Component | Technology |
|---|---|
| Language | Go 1.21+ |
| Framework | GoServe v2 |
| API Gateway | Kong |
| Message Broker | NATS |
| Web Framework | Gin |
| Auth Database | PostgreSQL (pgx) |
| Blog Database | MongoDB (mongo-driver) |
| Cache | Redis (go-redis) |
| Migrations | golang-migrate |
| Authentication | JWT tokens |
| Validation | validator |
| Configuration | Environment variables |
Quick Start
Prerequisites
- Docker & Docker Compose (Installation Guide)
- Go 1.21+ (for local development)
Installation
1. Clone the Repository
git clone https://github.com/afteracademy/gomicro.git
cd gomicro
2. Generate RSA Keys
go run .tools/rsa/keygen.go
3. Create Environment Files
go run .tools/copy/envs.go
4. Start with Docker Compose
# Full stack with all services
docker compose up --build
The API will be available at: http://localhost:8000 (via Kong Gateway)
5. Health Check
# Check Kong Gateway
curl http://localhost:8001/status
# Check NATS
curl http://localhost:8222/varz
Access Points
| Service | URL | Description |
|---|---|---|
| Kong Gateway | http://localhost:8000 | API Entry Point |
| Kong Admin | http://localhost:8001 | Kong Configuration |
| NATS Monitoring | http://localhost:8222 | NATS Dashboard |
| PostgreSQL | localhost:5432 | Auth Database |
| MongoDB | localhost:27017 | Blog Database |
| Redis (Auth) | localhost:6379 | Auth Cache |
| Redis (Blog) | localhost:6380 | Blog Cache |
Development Tools (with docker-compose.dev.yml):
| Tool | URL | Purpose |
|---|---|---|
| pgAdmin | http://localhost:5050 | PostgreSQL Management |
| Mongo Express | http://localhost:8082 | MongoDB Management |
| Redis Commander | http://localhost:8083 | Redis Management |
Troubleshooting
If you encounter issues:
- Ensure ports 8000, 8001, 5432, 27017, 6379, 6380, 4222 are available
- Check service logs:
docker compose logs -f [service_name] - Clean slate:
docker compose down -v && docker compose up --build
For detailed setup, usage, and troubleshooting: README-DOCKER.md
Deployment Scenarios
1. Full Stack Development (Recommended)
docker compose up --build
Starts all services with Kong, NATS, and shared databases.
Adds pgAdmin, Mongo Express, and Redis Commander for database management.
2. Individual Service Development
# Auth service only
cd auth_service && docker compose up --build
# Blog service only
cd blog_service && docker compose up --build
Runs a single service in isolation for fast iteration and debugging.
3. Load Balanced Production
docker compose -f docker-compose-load-balanced.yml up --build
Runs 2 instances of each service behind Kong for production-like setup.
Architecture
Microservices Design Principles
This project follows microservices best practices:
- Service Isolation - Each service has its own database and cache
- Independent Deployment - Services can be deployed independently
- API Gateway Pattern - Single entry point via Kong
- Event-Driven Communication - NATS for async messaging
- Database per Service - No shared databases
- Distributed Authentication - Auth service validates tokens via NATS
- Health Checks - Service health monitoring and dependency management
System Architecture
1. Without Load Balancing

2. With Load Balancing

Request Flow
Client β Kong Gateway β API Key Validation β Service β NATS β Response
- Client Request β Kong Gateway (port 8000)
- API Key Validation β Custom Kong plugin calls
auth:8080/verify/apikey - Route to Service β Kong forwards to auth or blog service
- Service Processing β Business logic execution
- NATS Communication β Inter-service messaging (if needed)
- Response β Kong β Client
Authentication Flow
- Users & Credentials β Stored in auth_service PostgreSQL database
- JWT Token Generation β Auth service creates access/refresh tokens
- Token Validation β Auth service middleware validates JWT
- Cross-Service Auth β Blog service requests token validation via NATS
- Distributed Security β Each service can enforce its own authentication
Authorization Flow
- Roles & Permissions β Stored in auth_service PostgreSQL database
- Role Assignment β Users can have multiple roles
- Role Validation β Auth service middleware checks permissions
- Cross-Service Authorization β Blog service requests role validation via NATS
- Fine-Grained Control β Each service decides which endpoints require which roles
Design Philosophy: This distributed authentication/authorization gives each service autonomy to define public, protected, and restricted APIs independently while maintaining centralized user management.
Service Communication
Synchronous (HTTP)
- Client β Kong Gateway
- Kong β Services (routing)
- Kong Plugin β Auth Service (API key validation)
Asynchronous (NATS)
- Blog Service β Auth Service (token validation)
- Blog Service β Auth Service (role verification)
- Event-driven messaging between services
Network Architecture
- Custom Bridge Network (
gomicro-network) for service discovery - Container Names as DNS (postgres, mongo, redis-auth, redis-blog, nats)
- Internal Communication via container names (no external IPs)
- External Access only via Kong Gateway
- Database Access exposed for development (can be restricted in production)
Project Structure
gomicro/
βββ auth_service/ # Authentication & Authorization Service
β βββ api/
β β βββ auth/ # Auth endpoints (signup, signin, refresh)
β β β βββ dto/ # Request/response DTOs
β β β βββ message/ # NATS message definitions
β β β βββ middleware/ # Auth & authorization middleware
β β β βββ model/ # PostgreSQL models
β β βββ user/ # User management endpoints
β βββ cmd/main.go # Service entry point
β βββ migrations/ # PostgreSQL migrations
β βββ startup/ # Server initialization
β βββ docker-compose.yml # Standalone development
β
βββ blog_service/ # Blog Management Service
β βββ api/
β β βββ author/ # Author-specific blog operations
β β βββ blog/ # Blog CRUD operations
β β βββ blogs/ # Blog listing & search
β β βββ editor/ # Editorial operations
β βββ cmd/main.go # Service entry point
β βββ startup/ # Server initialization & indexes
β βββ docker-compose.yml # Standalone development
β
βββ kong/ # API Gateway Configuration
β βββ kong.yml # Kong declarative config
β βββ kong-load-balanced.yml # Load balanced config
β βββ apikey_auth_plugin/ # Custom Go plugin for API key validation
β
βββ docker-compose.yml # Full stack orchestration
βββ docker-compose.dev.yml # Development tools
βββ docker-compose-load-balanced.yml # Production setup
βββ README-DOCKER.md # Detailed Docker documentation
Service Directories
| Directory | Purpose |
|---|---|
| api/ | Feature-based API implementations |
| cmd/ | Application entry point (main.go) |
| common/ | Shared code across APIs |
| config/ | Environment configuration |
| keys/ | RSA keys for JWT signing |
| migrations/ | Database migration files (auth service) |
| startup/ | Server, DB, Redis, NATS initialization |
| utils/ | Utility functions |
Helper Directories
| Directory | Purpose |
|---|---|
| .extra/ | Database init scripts, documentation, assets |
| .tools/ | RSA key generator, env file copier |
| .vscode/ | Editor configuration, debug settings |
| .docs/ | Architecture diagrams, banners |
Code Examples
NATS Message Definition
Create message types for inter-service communication:
package message
type TokenValidation struct {
AccessToken string `json:"accessToken,omitempty"`
}
func NewTokenValidation(token string) *TokenValidation {
return &TokenValidation{
AccessToken: token,
}
}
Controller with NATS Endpoints
Controllers implement micro.Controller to handle both HTTP and NATS requests:
package auth
import (
"github.com/gin-gonic/gin"
"github.com/afteracademy/gomicro/auth_service/api/auth/message"
"github.com/afteracademy/goserve/v2/micro"
"github.com/afteracademy/goserve/v2/network"
)
type controller struct {
micro.Controller
service Service
}
func NewController(
authMFunc network.AuthenticationProvider,
authorizeMFunc network.AuthorizationProvider,
service Service,
) micro.Controller {
return &controller{
Controller: micro.NewController("/auth", authMFunc, authorizeMFunc),
service: service,
}
}
// MountNats - Endpoints other services can call via NATS
func (c *controller) MountNats(group micro.NatsGroup) {
group.AddEndpoint("validate.token", micro.NatsHandlerFunc(c.validateTokenHandler))
group.AddEndpoint("validate.role", micro.NatsHandlerFunc(c.validateRoleHandler))
}
// MountRoutes - HTTP endpoints for clients
func (c *controller) MountRoutes(group *gin.RouterGroup) {
group.POST("/signup/basic", c.signupBasicHandler)
group.POST("/signin/basic", c.signinBasicHandler)
group.POST("/token/refresh", c.Authentication(), c.tokenRefreshHandler)
group.DELETE("/logout", c.Authentication(), c.logoutHandler)
}
func (c *controller) validateTokenHandler(req micro.NatsRequest) {
var msg message.TokenValidation
if err := req.DecodeData(&msg); err != nil {
micro.SendNatsErrorMessage(err)
return
}
user, err := c.service.ValidateToken(msg.AccessToken)
if err != nil {
micro.SendNatsErrorMessage(err)
return
}
micro.SendNatsMessage(user)
}
// HTTP handlers...
func (c *controller) signupBasicHandler(ctx *gin.Context) {
// Implementation...
}
Key Components:
MountNats()- Defines NATS endpoints for inter-service callsMountRoutes()- Defines HTTP endpoints for client requestsmicro.Controller- Interface for microservice controllers
Service with NATS Communication
Services use micro.RequestNats to call other services via NATS messaging:
package blog
import (
authmsg "github.com/afteracademy/gomicro/auth_service/api/auth/message"
"github.com/afteracademy/goserve/v2/micro"
"github.com/afteracademy/goserve/v2/mongo"
"github.com/afteracademy/goserve/v2/redis"
)
const NATS_AUTH_VALIDATE_TOKEN = "auth.validate.token"
const NATS_AUTH_VALIDATE_ROLE = "auth.validate.role"
type Service interface {
ValidateUserToken(token string) (*authmsg.User, error)
ValidateUserRole(userId, roleCode string) (bool, error)
// ... other blog operations
}
type service struct {
natsClient micro.NatsClient
blogQueryBuilder mongo.QueryBuilder[model.Blog]
blogCache redis.Cache[dto.BlogInfo]
}
func NewService(
db mongo.Database,
store redis.Store,
natsClient micro.NatsClient,
) Service {
return &service{
natsClient: natsClient,
blogQueryBuilder: mongo.NewQueryBuilder[model.Blog](db, model.CollectionName),
blogCache: redis.NewCache[dto.BlogInfo](store),
}
}
// Call auth service via NATS to validate token
func (s *service) ValidateUserToken(token string) (*authmsg.User, error) {
request := authmsg.NewTokenValidation(token)
// Send request to auth service via NATS and wait for response
user, err := micro.RequestNats[authmsg.TokenValidation, authmsg.User](
s.natsClient,
NATS_AUTH_VALIDATE_TOKEN,
request,
)
if err != nil {
return nil, err
}
return user, nil
}
// Call auth service via NATS to validate role
func (s *service) ValidateUserRole(userId, roleCode string) (bool, error) {
request := authmsg.NewRoleValidation(userId, roleCode)
result, err := micro.RequestNats[authmsg.RoleValidation, authmsg.RoleResult](
s.natsClient,
NATS_AUTH_VALIDATE_ROLE,
request,
)
if err != nil {
return false, err
}
return result.HasRole, nil
}
Key Features:
- Type-Safe NATS Calls - Generic
RequestNats[Request, Response] - Async Communication - Non-blocking inter-service messaging
- Error Handling - Proper error propagation across services
- Distributed Auth - Services don't need auth logic, just call auth service
NATS Client Setup
Initialize NATS client in service startup:
package startup
import (
"time"
"github.com/afteracademy/goserve/v2/micro"
)
func SetupNats(env *config.Env) micro.NatsClient {
natsConfig := micro.Config{
NatsUrl: env.NatsUrl, // "nats://nats:4222"
NatsServiceName: env.NatsServiceName, // "auth" or "blog"
NatsServiceVersion: env.NatsServiceVersion, // "1.0.0"
Timeout: time.Second * 10,
}
return micro.NewNatsClient(&natsConfig)
}
NATS Documentation: GoServe wraps nats-io/nats.go for simplified microservice patterns.
Migration Guide
From GoServe Monolith to Microservices
If you're coming from the GoServe monolithic framework:
| Monolithic | Microservices | Change |
|---|---|---|
network.Module[T] |
micro.Module[T] |
Module initialization |
network.NewRouter() |
micro.NewRouter() |
Router creation |
network.BaseController |
micro.BaseController |
Base controller interface |
network.Controller |
micro.Controller |
Controller interface |
| N/A | MountNats(group) |
NATS endpoint registration |
New Capabilities:
micro.NatsClient- NATS client for inter-service communicationmicro.RequestNats[Req, Res]()- Type-safe NATS request/responsemicro.NatsHandlerFunc- NATS message handlersMountNats()- Register NATS endpoints alongside HTTP routes
API Documentation
Complete API documentation with authentication flows, request/response examples, and microservices patterns
Related Projects
Explore the GoServe ecosystem:
-
GoServe Framework
Core framework with PostgreSQL, MongoDB, Redis, and NATS support -
PostgreSQL API Server
Monolithic REST API with PostgreSQL and clean architecture -
MongoDB API Server
Complete REST API with MongoDB implementation -
GoServeGen CLI
Code generator for scaffolding new projects and APIs
Articles & Tutorials
Learn the concepts behind this project:
- How to Create Microservices β A Practical Guide Using Go
- How to Architect Good Go Backend REST API Services
- Implement JSON Web Token (JWT) Authentication using AccessToken and RefreshToken
Contributing
We welcome contributions! Please feel free to:
- Fork the repository
- Open issues for bugs or feature requests
- Submit pull requests with improvements
- Share your feedback and suggestions
Learn More
Subscribe to AfterAcademy on YouTube for in-depth tutorials and microservices concepts:
License
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Support This Project
If you find this project useful, please consider:
- Starring β this repository
- Sharing with the Go community
- Contributing improvements
- Reporting bugs and issues
- Writing articles about your experience
Built with β€οΈ by AfterAcademy
GoServe Framework β’ API Documentation β’ Docker Guide β’ Articles β’ YouTube