Search code examples
goarchitecturemicroservices

Sharing models between microservices


I'm trying to develop my first microservices (actors, movies, users) and I might be wrong about its concepts.
Here is the structure of my project.

project
├── actors/
│   ├── cmd/...
│   ├── internal/
│   │   ├── handlers/handlers.go
│   │   ├── models/models.go
│   │   └── services/services.go
│   └── ...
├── movies/
│   ├── cmd/...
│   ├── internal/
│   │   ├── handlers/handlers.go
│   │   ├── models/models.go
│   │   └── services/services.go
│   └── ...
└── ...

I planned to run them independently, one microservice per Docker container. Now I can't solve problem with my related models, because go forbids importing from internal and even I somehow import model I'm gonna have to copy extra files to container (or is it only possible way?):

package models

type Actor struct {
    ID        uint   `json:"id"`
    Name      string `json:"name"`
    Gender    string `json:"gender"`
    Birthdate string `json:"birthdate"`
}
package models

import (
    "main/actors/internal/models"  // Broken Import!!!
)

type Movie struct {
    ID      uint           `json:"id"`
    Name    string         `json:"name"`
    Release string         `json:"release"`
    Rating  uint           `json:"rating"`
    Actors  []models.Actor `json:"actors"`
}

Is there some good practices for sharing between microservices?


Solution

  • If you have types shared between services it's better to create a separate package for this. Let me explain a bit.

    Separate services – separate repositories and deployments So when you say that you want to run them independently it's assumed that services are separate repositories in Git, have separate versioning and CD pipelines.

    This is an important aspect as if you assume to have a monorepo recommendations will be different.

    In this case you need a separate repository that stores your domain types and which microservices import. This is a good approach as your domain models are versioned, so you can change models and gradually switch services to a new version. With all consequences that usually follow schemas evolution.

    One repository

    As I said this option is worse from my point of view as practically you will end up with monolith instead of microservices. But, if you still like an idea, I assume, a structure should be

    project
    ├── cmd
    │   ├── actors
    │   │   └── internal
    │   │       ├── handlers/handlers.go
    │   │       └── services/services.go
    │   └── movies
    │       └── internal
    │           ├── handlers/handlers.go
    │           └── services/services.go
    └── internal
        └── domain
            └── models/models.go