"ToDo API" Microservice Example
Introduction
Welcome!
This is an educational repository that includes a microservice written in Go. It is used as the principal example of my video series: Building Microservices in Go.
It's a collection of patterns and guidelines I've successfully used to deliver enterprise microservices when using Go.
The whole purpose of this project is to give you an idea about structuring your Go project with 3 principal goals:
- It is enterprise, meant to last for years,
- It allows a team to collaborate efficiently with little friction, and
- It is as idiomatic as possible.
Join the fun at https://youtube.com/MarioCarrion.
Domain Driven Design
This project uses a lot of the ideas introduced by Eric Evans in his book Domain Driven Design, I do encourage reading that book but before I think reading Domain-Driven Design Distilled makes more sense, also there's a free to download DDD Reference available as well.
On YouTube I created a playlist that includes some of my favorite talks and webinars, feel free to explore that as well.
Project Structure
Talking specifically about microservices only, the structure I like to recommended is the following, everything using <
and >
depends on the domain being implemented and the bounded context being defined.
-
build/
: defines the code used for creating infrastructure.-
: define concrete cloud provider./ -
: contains a Dockerfile used for building the binary./
-
-
cmd/
-
: uses primary database./ -
: uses readonly databases./ -
/
-
-
db/
-
migrations/
: contains database migrations. -
seeds/
: contains file meant to populate basic database values.
-
-
internal/
: defines the core domain.-
: a concrete repository used by the domain, for example/ postgresql
-
http/
: defines HTTP Handlers. -
service/
: orchestrates use cases and manages transactions.
-
-
pkg/
public API meant to be imported by other Go package.
There are cases where requiring a new bounded context is needed, in those cases the recommendation would be to define a package like internal/
that then should follow the same structure, for example:
internal/
/ internal/
/ internal/
/http internal/
/service
Tools
go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/[email protected]
go install github.com/kyleconroy/sqlc/cmd/[email protected]
go install github.com/maxbrunsfeld/counterfeiter/[email protected]
go install github.com/deepmap/oapi-codegen/cmd/[email protected]
Features
Icons meaning:
In no particular order:
- Database migrations
- Repository Pattern
- Project Layout
- Dependency Injection
- Secure Configuration
- OpenAPI 3 and Swagger-UI
- Infrastructure as code
- Metrics, Traces and Logging using OpenTelemetry
- Error Handling
- Caching
- Persistent Storage (using PostgreSQL)
- Authorization
- REST APIs
- Events
- Testing
- Type-safe mocks with
maxbrunsfeld/counterfeiter
- Equality with
google/go-cmp
- REST APIs
- Integration tests for Datastores with
ory/dockertest
- Type-safe mocks with
- Containerization using Docker
- Whatever else I forgot to include
More ideas
- 2016: Peter Bourgon's: Repository structure
- 2016: Ben Johnson's: Standard Package Layout
- 2017: William Kennedy's: Design Philosophy On Packaging
- 2017: Jaana Dogan's: Style guideline for Go packages
- 2018: Kat Zien - How Do You Structure Your Go Apps
Docker Containers
Please notice in order to run this project locally you need to run a few programs in advance, if you use Docker please refer to the concrete instructions in docs/
for more details.
There's also a docker-compose.yml, covered in Building Microservices In Go: Containerization with Docker, however like I mentioned in the video you have to execute docker-compose
in three steps:
- Run
docker-compose up
, here the api service will fail because thepostgres
service takes longer to start. - Run
docker-compose up api
, api will successfully start however interacting with it will fail because the database migrations are missing. - Run
docker-compose run api migrate -path /api/migrations/ -database postgres://user:password@postgres:5432/dbname?sslmode=disable up
to finally have everything working correctly.