- Microservices: Each service is independently deployable, scalable and follows the single responsibility principle (each service does one thing well)
- Backend-for-Frontend (BFF): Designed for tailored client experiences (this means the API Gateway is optimized for a singular frontend)
- API Gateway Pattern: Single entry point for all client requests, routing to appropriate services
- Database per Service: Each microservice manages its own database schema and data
- Hybrid Architecture: Check out the communication patterns section for more details on how services communicate with each other
- Service Isolation: Internal services not exposed to public network (only API Gateway is public)
- Centralized Tooling: Shared tests, tools, CLIs, and scripts for build and deployment automation
fafnir/
├── build/ # Build configurations
│ └── docker/ # Centralized Dockerfiles
├── deployments/ # Deployment configurations
│ ├── archive/ # Archive folder containing old Kubernetes manifests
│ │ └── k8s/ # Kubernetes Manifests
│ ├── docker/ # Docker Compose files
│ └── helm/ # Helm charts
├── docs/ # Documentation
│ └── designs/ # Excalidraw designs and images
├── infra/ # Infrastructure configurations
│ ├── broker/ # NATS JetStream broker configurations (initialization scripts)
│ ├── db/ # Database configurations (initialization scripts)
│ ├── env/ # Environment variables
│ └── monitoring/ # Prometheus, Loki, and Grafana configurations
├── proto/ # Protocol buffer definitions
├── src/ # Source code for microservices
│ ├── api-gateway/ # GraphQL API Gateway
│ ├── auth-service/ # Authentication service
│ ├── order-service/ # Order service
│ ├── portfolio-service/ # Portfolio service
│ ├── security-service/ # Authorization service
│ ├── shared/ # Shared libraries and utilities (logging, tools, etc.)
│ ├── stock-service/ # Stock service
│ ├── trade-engine/ # Trade engine service
│ └── user-service/ # User management service
├── tests/ # Testing suites
│ ├── e2e/ # End-to-end tests
│ └── locust/ # Load testing with Locust
├── tools/ # Development tools
│ ├── cli/ # some dev CLIs
│ │ └── seedctl/ # Database seeder
│ └── scripts/ # Build and deployment scripts
├── .gitattributes
├── .gitignore
├── LICENSE
├── Makefile # Build automation
└── README.md # Project overview and documentation
| Service | Description | Tech Stack | Ports | Database |
|---|---|---|---|---|
| api-gateway | GraphQL API Gateway - Single entry point for all client requests | Go, gqlgen, go-chi, promhttp | 8080 (public) | - |
| auth-service | Authentication & JWT token management | Go, sqlc, go-chi, promhttp | 8081 (internal) | auth_db |
| security-service | Role-based access control and authorization | Go, sqlc, gRPC, promhttp | 8082 (internal) | security_db |
| user-service | User profile management and CRUD operations | Go, sqlc, gRPC, promhttp | 8083 (internal) | user_db |
| stock-service | Stock quote and metadata information | Go, sqlc, gRPC, promhttp | 8084 (internal) | stock_db, redis-0 |
| order-service | Order processing and order history | Go, sqlc, gRPC, promhttp | 8085 (internal) | order_db |
| portfolio-service | Portfolio management, performance tracking, and reporting | Go, sqlc, gRPC, promhttp | 8086 (internal) | portfolio_db |
| trade-engine | Trade execution and settlement logic | Go, sqlc, gRPC, promhttp | 8087 (internal) | redis-1 |
| shared | Shared libraries, utilities, and common code | Go | - | - |
| Service | Description | Ports | Purpose |
|---|---|---|---|
| postgres | Postgres database with per-service databases | 5432 (internal) | Data persistence |
| redis | Redis caching for quick look up | 6379 (internal) | Caching |
| prometheus | Metrics collection and monitoring | 9090 (dev only) | Observability |
| loki | Unified logging storage | 3100 (dev only) | Observability |
| grafana | Dashboard and Observability UI | 3000 (dev only) | Observability |
| nats jetstream | Persistent event streaming message broker | 4222 (internal) | Event Streaming |
| locust | Load testing tool for simulating concurrent users | 8089 (dev only) | Load testing |
This architecture employs a combination of synchronous and asynchronous communication patterns. It is both event driven and request-response based, depending on the use case and service requirements.
- Synchronous Communication: The API Gateway handles client requests and routes them to the appropriate microservices using REST or gRPC.
- This is used for request-response interactions where the client expects an immediate response, such as fetching user profiles or stock quotes.
- Asynchronous Communication: Microservices communicate with each other using NATS JetStream for event-driven interactions, allowing for decoupled and scalable service interactions.
- This is used for scenarios like user registration events, order processing, and trade execution, where services can publish events to NATS and other services can subscribe to those events without needing to wait for an immediate response.
Feel free to take a look at the designs folder for visual representations of architecture, network, and data flow designs.
- Microservices by Martin Fowler
- What is Microservices Architecture? by Anjaly Chandran
- A pattern language for microservices by Chris Richardson
- 19 Microservices Patterns for System Design Interviews by Soma
- A Crash Course on Microservices Design Patterns by ByteByteGo
- NATS Documentation by NATS
- Kubernetes Documentation by Kubernetes
- Helm Documentation by Helm
- Prometheus Documentation by Prometheus
- Loki Documentation by Grafana
- Grafana Documentation by Grafana