A production-ready GraphQL service built in Go, demonstrating Clean Architecture principles with Domain-Driven Design (DDD) patterns. This project serves as both a functional GraphQL API and an educational reference for building scalable web services.
- GraphQL API: Schema-first GraphQL implementation with gqlgen
- Clean Architecture: Clear separation of concerns across domain, application, infrastructure, and interface layers
- User Management: Complete CRUD operations with pagination support
- Database Integration: PostgreSQL with migrations and connection pooling
- Docker Support: Multi-stage builds with development and production configurations
- Configuration Management: Environment-based configuration with validation
- Structured Logging: JSON-formatted logging with configurable levels
- Health Checks: Built-in health monitoring and startup validation
- Testing: Comprehensive unit and integration tests with mocking
- Development Tools: Makefile automation and Docker Compose setup
- Quick Start
- Architecture
- API Documentation
- Development
- Docker Deployment
- Testing
- Configuration
- Contributing
- License
- Go 1.24.3 or later
- PostgreSQL 12+ (or use Docker Compose)
- Make (optional, for convenience commands)
-
Clone the repository
git clone https://github.com/captain-corgi/go-graphql-example.git cd go-graphql-example -
Start all services
make docker-run # or manually: docker-compose up -d -
Access the GraphQL Playground
make playground # or visit: http://localhost:8080/playground
-
Install dependencies
make setup
-
Start PostgreSQL (if not using Docker)
# Using Docker for database only docker run --name postgres -e POSTGRES_PASSWORD=postgres -e POSTGRES_DB=graphql_service -p 5432:5432 -d postgres:16-alpine -
Run migrations
make migrate-up
-
Start the development server
make dev
This project implements Clean Architecture with the following layers:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Interfaces Layer β
β βββββββββββββββββββ βββββββββββββββββββ β
β β GraphQL β β HTTP Server β β
β β Resolvers β β & Middleware β β
β βββββββββββββββββββ βββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Application Layer β
β βββββββββββββββββββ βββββββββββββββββββ β
β β Use Cases β β DTOs & β β
β β & Services β β Orchestration β β
β βββββββββββββββββββ βββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Domain Layer β
β βββββββββββββββββββ βββββββββββββββββββ β
β β Entities & β β Repository β β
β β Value Objects β β Interfaces β β
β βββββββββββββββββββ βββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Infrastructure Layer β
β βββββββββββββββββββ βββββββββββββββββββ β
β β Database β β Configuration β β
β β Repositories β β & Logging β β
β βββββββββββββββββββ βββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
- Dependency Inversion: Inner layers define interfaces, outer layers implement them
- Framework Independence: Business logic is isolated from frameworks
- Testability: Easy mocking and testing through dependency injection
- Single Responsibility: Each layer has a clear, focused purpose
- URL:
http://localhost:8080/query - Playground:
http://localhost:8080/playground - Health Check:
http://localhost:8080/health
Get a user by ID:
query GetUser {
user(id: "550e8400-e29b-41d4-a716-446655440001") {
id
email
name
createdAt
updatedAt
}
}List users with pagination:
query GetUsers {
users(first: 10) {
edges {
node {
id
email
name
}
cursor
}
pageInfo {
hasNextPage
endCursor
}
}
}Create a new user:
mutation CreateUser {
createUser(input: {
email: "[email protected]"
name: "John Doe"
}) {
user {
id
email
name
}
errors {
message
field
}
}
}For more examples, see the examples/graphql/ directory.
# Development
make dev # Run with development config
make run # Run the application
make build # Build binary
make clean # Clean build artifacts
# Code Generation
make generate # Generate all code (GraphQL + mocks)
make generate-graphql # Generate GraphQL code only
make generate-mocks # Generate mocks only
# Testing
make test # Run all tests
make test-integration # Run integration tests
make coverage # Generate coverage report
# Database
make migrate-up # Run migrations
make migrate-down # Rollback migrations
make migrate-create NAME=migration_name # Create new migration
# Docker
make docker-run # Start with Docker Compose
make docker-stop # Stop Docker services
make docker-clean # Clean Docker resources
# Code Quality
make lint # Run linters
make format # Format code
make check # Run all checks
# Utilities
make setup # Setup development environment
make playground # Open GraphQL Playgroundβββ api/graphql/ # GraphQL schema files
βββ cmd/server/ # Application entry point
βββ internal/
β βββ application/ # Use cases and services
β βββ domain/ # Core business logic
β βββ infrastructure/ # External adapters
β βββ interfaces/ # Delivery layer
βββ migrations/ # Database migrations
βββ configs/ # Configuration files
βββ examples/ # API usage examples
βββ docs/ # Documentation
βββ scripts/ # Utility scripts
- Define GraphQL Schema: Add types to
api/graphql/*.graphqls - Generate Code: Run
make generate-graphql - Implement Domain Logic: Add entities and repositories in
internal/domain/ - Create Use Cases: Add services in
internal/application/ - Implement Resolvers: Update resolvers in
internal/interfaces/graphql/resolver/ - Add Tests: Write unit and integration tests
- Update Documentation: Update relevant docs
# Start all services (includes database)
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down# Build and start production services
make docker-prod-build
# Or manually
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d --build# Required for production
export POSTGRES_PASSWORD=your_secure_password
export DATABASE_URL=postgres://user:pass@host:5432/dbname?sslmode=require
# Optional
export POSTGRES_DB=graphql_service
export POSTGRES_USER=postgres# All tests
make test
# With coverage
make coverage
# Integration tests only
make test-integration
# Specific package
go test ./internal/domain/user/...- Unit Tests: Test individual components in isolation
- Integration Tests: Test component interactions with real database
- Mocks: Generated mocks for all interfaces using gomock
//go:generate go run github.com/golang/mock/mockgen -source=$GOFILE -destination=./mocks/mock_$GOFILE -package=mocks
// Add this directive to interface files for automatic mock generationConfiguration is managed through YAML files with environment variable overrides:
configs/config.yaml- Base configurationconfigs/config.development.yaml- Development overridesconfigs/config.docker.yaml- Docker environmentconfigs/config.production.yaml- Production settings
# Application
CONFIG_FILE=path/to/config.yaml
GIN_MODE=release
# Database
DATABASE_URL=postgres://user:pass@host:5432/dbname
# Logging
LOG_LEVEL=info
LOG_FORMAT=jsonWe welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Make your changes following our coding standards
- Add tests for new functionality
- Run the test suite:
make check - Commit your changes:
git commit -m 'Add amazing feature' - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
- Follow Go conventions and idioms
- Maintain Clean Architecture boundaries
- Write comprehensive tests
- Update documentation for new features
- Use conventional commit messages
This project is licensed under the MIT License - see the LICENSE file for details.
- gqlgen for GraphQL code generation
- Gin for the HTTP framework
- Clean Architecture by Robert C. Martin
- Domain-Driven Design by Eric Evans
- π Documentation
- π Issue Tracker
- π¬ Discussions
Happy coding! π