← ademola.dev / writing 6 min read
share →
GoSystem DesignPythonMicroserviceKafka

Part One: Designing and Building a Microservice with Golang, Python, and Clean Architecture

Golang is designed for simplicity, scalability, and high performance · Mon, Jan 13, 2025
Part One: Designing and Building a Microservice with Golang, Python, and Clean Architecture

I started learning Go three years ago as a second programming language, seeking a scalable, efficient, and versatile technology. Since then, I’ve been captivated by its power and simplicity. Realio reflects my passion for creating feature-rich applications that serve as learning experiences for myself and others.

What is Realio?

Realio is an innovative property management and investment platform designed to transform the real estate industry. Inspired by leading solutions like Zillow and Airbnb, it enables seamless property exploration, personalized recommendations, and efficient appointment scheduling.

Built with a robust microservices architecture, Realio ensures unparalleled scalability, maintainability, and performance.

Why Golang for Realio?

Go is statically typed and compiled, making it exceptionally fast. Its goroutines make concurrent programming intuitive — perfect for a microservices platform handling thousands of simultaneous requests.

Architecture Overview

realio/
├── auth-service/          # Go — JWT, OAuth2
├── property-service/      # Go — listings, search
├── recommendation-engine/ # Python — ML recommendations
├── notification-service/  # Go — push, email, SMS
├── api-gateway/           # Go — routing, rate limiting
└── infra/
    ├── kafka/             # Event streaming
    ├── postgres/          # Primary storage
    └── redis/             # Caching layer

Clean Architecture Layers

Each service follows the same layered structure:

// Domain layer — pure business logic
type Property struct {
  ID          string
  Title       string
  Price       float64
  Location    Location
  OwnerID     string
}

type PropertyRepository interface {
  FindByID(ctx context.Context, id string) (*Property, error)
  Search(ctx context.Context, filters SearchFilters) ([]Property, error)
  Save(ctx context.Context, p *Property) error
}
// Use-case layer — orchestrates domain logic
type ListPropertyUseCase struct {
  repo   PropertyRepository
  events EventPublisher
}

func (uc *ListPropertyUseCase) Execute(ctx context.Context, req ListRequest) (*Property, error) {
  p := domain.NewProperty(req.Title, req.Price, req.Location, req.OwnerID)
  if err := uc.repo.Save(ctx, p); err != nil {
    return nil, err
  }
  uc.events.Publish("property.listed", p)
  return p, nil
}

Inter-Service Communication

Services communicate via Kafka for async events and gRPC for sync calls:

// Publishing a domain event
func (p *KafkaPublisher) Publish(topic string, payload any) error {
  data, _ := json.Marshal(payload)
  return p.writer.WriteMessages(context.Background(),
    kafka.Message{
      Topic: topic,
      Value: data,
    },
  )
}

What’s Next

Part Two covers the Python recommendation engine, how it consumes Kafka events from the property service, and how the ML model is served alongside the Go services.

thoughts on this?

Hit reply — I read every email.

hello@demola.dev →
← Previous Effortless Concurrency: Unveiling the Power of Asynq Messaging Queue in Go Next → Getting Started with Jetpack Compose: A Flutter Developer's Perspective