Go GraphQL Example

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.
π Features
- 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
π Table of Contents
π Quick Start
Prerequisites
- Go 1.24.3 or later
- PostgreSQL 12+ (or use Docker Compose)
- Make (optional, for convenience commands)
Using Docker Compose (Recommended)
-
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
Local Development Setup
-
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
π Architecture
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 β β
β βββββββββββββββββββ βββββββββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Key Principles
- 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
π API Documentation
GraphQL Endpoint
- URL:
http://localhost:8080/query
- Playground:
http://localhost:8080/playground
- Health Check:
http://localhost:8080/health
Example Queries
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: "user@example.com"
name: "John Doe"
}) {
user {
id
email
name
}
errors {
message
field
}
}
}
For more examples, see the examples/graphql/ directory.
π Development
Available Make Commands
# 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
Project Structure
βββ 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
Adding New Features
- 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
π³ Docker Deployment
Development
# Start all services (includes database)
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down
Production
# 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
Environment Variables for Production
# 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
π§ͺ Testing
Running Tests
# All tests
make test
# With coverage
make coverage
# Integration tests only
make test-integration
# Specific package
go test ./internal/domain/user/...
Test Structure
- Unit Tests: Test individual components in isolation
- Integration Tests: Test component interactions with real database
- Mocks: Generated mocks for all interfaces using gomock
Writing Tests
//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 generation
βοΈ Configuration
Configuration is managed through YAML files with environment variable overrides:
Configuration Files
configs/config.yaml - Base configuration
configs/config.development.yaml - Development overrides
configs/config.docker.yaml - Docker environment
configs/config.production.yaml - Production settings
Environment Variables
# 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=json
π€ Contributing
We welcome contributions! Please see our Contributing Guide for details.
Development Workflow
- 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
Code Standards
- Follow Go conventions and idioms
- Maintain Clean Architecture boundaries
- Write comprehensive tests
- Update documentation for new features
- Use conventional commit messages
π License
This project is licensed under the MIT License - see the LICENSE file for details.
π Acknowledgments
π Support
Happy coding! π