CVT Server (Go Implementation)
The CVT server is a Go-based gRPC service that validates HTTP interactions against OpenAPI v2 and v3 specifications.
Architecture
- Language: Go 1.25
- Framework: gRPC
- Validation Engine: kin-openapi
- Caching: Ristretto (max 1000 schemas, 24h TTL, LRU eviction)
- Logging: Zap (structured logging)
- Health Checks: gRPC Health Check Protocol
Key Advantages over Java Implementation
- Image Size: ~30-40MB (vs ~200MB+ for Java)
- Startup Time: <1 second (vs 3-5 seconds for Java)
- Memory Usage: ~50-100MB (vs ~512MB+ for Java)
- Binary Size: ~19MB (single static binary)
- No Runtime Dependencies: Doesn't require JVM
Project Structure
server/
├── main.go # Server entry point (thin wrapper)
├── cvtservice/ # Core service implementation (importable package)
│ ├── validator_service.go # Core validation service (RegisterSchema, ValidateInteraction, CanIDeploy)
│ ├── compatibility_engine.go # Breaking change detection between schema versions
│ ├── validation_utils.go # Input validation utilities
│ ├── cache.go # Ristretto cache for schemas and consumers
│ ├── health.go # gRPC health check service
│ ├── logger.go # Structured logging with Zap
│ ├── metrics.go # Prometheus metrics
│ ├── auth.go # API key authentication
│ ├── tls.go # TLS/mTLS configuration
│ ├── audit_logger.go # Audit logging for compliance
│ └── *_test.go # Comprehensive test suite
├── storage/ # Persistent storage layer
│ ├── storage.go # Storage interface
│ ├── config.go # Storage configuration
│ ├── sqlite/ # SQLite backend
│ └── postgres/ # PostgreSQL backend
├── pb/ # Generated protobuf code
│ ├── cvt.pb.go
│ └── cvt_grpc.pb.go
├── testdata/ # Test fixtures
├── go.mod # Go module dependencies
├── go.sum # Dependency checksums
├── Dockerfile # Multi-stage Docker build
└── README.md # This file
Package Structure
The server is organized as an importable library (cvtservice) with a thin main wrapper:
server/main.go: Entry point that imports and configures the service
server/cvtservice/: Core service logic (can be imported by CLI and other tools)
server/storage/: Pluggable persistence backends (SQLite, PostgreSQL, in-memory)
Building
Local Build
# Build the server binary
go build -o cvt-server .
# Or use Make
make build
Docker Build
# Build Docker image
docker build -t cvt-server .
# Or use Docker Compose
make up
Running
Run Locally
# Run directly
go run .
# Or run the built binary
./cvt-server
# Or use Make
make run-server
The server will start on port 9550 by default. You can change it by setting the CVT_PORT environment variable:
CVT_PORT=9552 go run .
Run in Docker
# Start with Docker Compose
make up
# Check health
make check-health
# View logs
make logs
# Stop
make down
Testing
Unit Tests
# Run all unit tests
go test -v ./server/cvtservice/...
# Or use Make
make test-server
# Run specific test
go test -v -run TestValidateSchemaID ./server/cvtservice/...
# Run tests with coverage
go test -v -coverprofile=coverage.out ./server/cvtservice/...
go tool cover -html=coverage.out
# Run storage tests
go test -v ./server/storage/...
Integration Tests
# Run integration tests (requires Docker)
go test -v -tags=integration ./...
# Or use Make
make test-integration
Cache Tests
# Run cache-specific tests
go test -v -run TestCache ./...
# Or use Make
make test-cache
Dependencies
Core dependencies (see go.mod for full list):
- kin-openapi (v0.133.0): OpenAPI 3.0/2.0 validation
- gRPC (v1.77.0): gRPC server implementation
- Ristretto (v0.2.0): High-performance caching
- Zap (v1.27.1): Structured logging
Validation Features
- Schema ID: Max 255 characters, not empty
- Schema Content: Max 10MB, not empty
- HTTP Method: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS (case-insensitive)
- HTTP Path: Must start with '/', not empty
- Status Code: Range 100-599
OpenAPI Validation (kin-openapi)
- Supports OpenAPI 2.0 (Swagger) and OpenAPI 3.0/3.1
- Request method validation
- Request path matching
- Request body schema validation
- Request header validation
- Response status code validation
- Response body schema validation
- Response header validation
- Complex schemas (allOf, refs, nested objects, arrays)
Caching
The server uses Ristretto for high-performance schema caching:
- Capacity: 1000 schemas max
- TTL: 24 hours
- Eviction: LRU (Least Recently Used)
- Thread-Safe: Concurrent access supported
- Metrics: Cache hits, misses, and evictions
Logging
Structured logging with Zap:
- Production Mode: JSON-formatted logs with timestamps
- Development Mode: Console-formatted logs with colors
- Log Levels: DEBUG, INFO, WARN, ERROR, FATAL
Example log output:
{
"level": "info",
"timestamp": "2025-11-26T21:51:00Z",
"msg": "Schema registered successfully",
"schemaId": "my-api-v1"
}
Health Checks
The server implements the gRPC Health Checking Protocol:
Available Services
| Service Name |
Description |
| `` (empty) |
Overall server health |
cvt.ContractValidator |
Validation service health |
Health Check Commands
# Install grpc-health-probe
make install-health-probe
# Quick health check
make health
# Detailed health check
make check-health
# Continuous monitoring
make watch-health
Manual Health Check
grpc-health-probe -addr=localhost:9550
grpc-health-probe -addr=localhost:9550 -service=cvt.ContractValidator
Docker
Image Details
- Base Image: Alpine 3.21 (~5MB)
- Final Image Size: ~30-40MB
- Build Time: ~2-3 minutes
- Multi-Stage Build: Yes (builder + runtime)
- Non-Root User: Yes (uid/gid 1000)
- Health Check: Built-in with grpc-health-probe
Build Optimizations
- Static binary (CGO_ENABLED=0)
- Debug symbols stripped (-ldflags="-w -s")
- Minimal runtime dependencies
- Layer caching for dependencies
Docker Commands
# Build image
docker build -t cvt-server .
# Run container
docker run -p 9550:9550 cvt-server
# Run with Docker Compose
docker compose up -d
# Check health
docker inspect cvt-server --format='{{.State.Health.Status}}'
Design Targets
- Validation Throughput: 5000+ validations/second (Baseline target)
- Schema Registration: <10ms per schema
- Memory Usage: ~50-100MB base, +~5MB per 100 cached schemas
- CPU Usage: Low (async I/O, efficient caching)
- Startup Time: <1 second
Note: Official benchmarking suite is currently under development (see docs/poc_status.md).
Optimization Tips
- Reuse Schemas: Register once, validate many times
- Monitor Cache: Check logs for cache hit/miss ratios
- Resource Allocation: 256MB RAM minimum, 512MB recommended
- Concurrent Requests: gRPC handles concurrency efficiently
Security
Current Implementation
- ✅ Input validation (schema size, format, paths)
- ✅ Non-root container user (uid/gid 1000)
- ✅ Structured logging (no sensitive data)
- ✅ Bounded caching (DoS protection)
- ⚠️ Insecure gRPC (no TLS/authentication)
Production Recommendations
- Enable TLS: Use grpc.Creds() with SSL/TLS certificates
- Add Authentication: Implement API keys or JWT tokens via interceptors
- Rate Limiting: Add per-client rate limits
- Network Security: Use firewall rules and VPC
- Monitoring: Enable metrics and alerting
Troubleshooting
Server Won't Start
# Check if port is in use
lsof -i :9550
# Check logs
go run . 2>&1 | grep -i error
# Run with debug logging
# (Edit logger.go: InitLogger(true) for development mode)
Build Errors
# Update dependencies
go mod tidy
go mod download
# Clear module cache
go clean -modcache
# Rebuild
go build -v .
Tests Failing
# Run with verbose output
go test -v ./...
# Run specific test
go test -v -run TestValidateSchemaID
# Check test coverage
go test -v -coverprofile=coverage.out ./...
Docker Issues
# Rebuild without cache
docker build --no-cache -t cvt-server .
# Check Docker logs
docker logs cvt-server
# Verify health
docker exec cvt-server /bin/grpc-health-probe -addr=:9550
Migrating from Java
Breaking Changes
None! The Go server maintains 100% compatibility with the existing SDKs and protobuf contracts:
- ✅ Same gRPC service definition
- ✅ Same request/response messages
- ✅ Same validation behavior
- ✅ Same error messages
- ✅ Same health check protocol
Deployment Strategy
- Test in Staging: Deploy Go server to staging environment
- Validate SDKs: Run SDK tests against Go server
- Performance Test: Compare throughput and latency
- Blue-Green Deploy: Run both servers temporarily
- Monitor: Watch metrics and logs closely
- Rollback Plan: Keep Java deployment ready if needed
Contributing
When adding new features:
- Write tests first (TDD approach)
- Maintain test coverage >70% (Enforced in CI/CD)
- Run
go fmt ./... before committing
- Run
go vet ./... to catch issues
- Update documentation
Resources