BTC LTP Service is a high-performance, enterprise-grade REST API service that provides real-time Last Traded Price (LTP) data for cryptocurrencies using Kraken Exchange API. Built with Clean Architecture principles and Domain-Driven Design, it implements a robust WebSocketβREST fallback pattern with intelligent caching and comprehensive observability.
- π Real-time Price Feeds - WebSocket primary, REST API fallback
- π Multiple Currency Pairs - BTC/USD, BTC/EUR, BTC/CHF, ETH/USD, and more
- β‘ Dual Cache Backend - Memory or Redis with configurable TTL
- π Prometheus Metrics - 30+ metrics for comprehensive monitoring
- π‘οΈ Rate Limiting - Token bucket algorithm with IP-based throttling
- π Structured Logging - JSON format with request tracing
- π³ Docker Ready - Multi-stage builds with security hardening
- βοΈ Clean Architecture - DDD patterns with clear separation of concerns
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β HTTP Client βββββΆβ Rate Limiter βββββΆβ API Gateway β
βββββββββββββββββββ ββββββββββββββββββββ βββββββββββββββββββ
β
ββββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ
β βΌ β
ββββββββββββββ βββββββββββββββββββββββββββββββββββββββ ββββββββββββββββ
β Prometheus β β BTC LTP Service β β Logging β
β Metrics β β (Clean Architecture DDD) β β (Structured) β
ββββββββββββββ βββββββββββββββββββββββββββββββββββββββ ββββββββββββββββ
β
ββββββββββββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ
β βΌ β
βββββββββββββββββ βββββββββββββββββββββββββββββββββββββββββ βββββββββββββββββ
β Cache Layer β β Fallback Exchange β β Config Mgmt β
β (Memory/Redis)β β WebSocket(1Β°) ββ REST API(2Β°) β β (YAML + ENV) β
βββββββββββββββββ βββββββββββββββββββββββββββββββββββββββββ βββββββββββββββββ
β
βββββββββββββΌβββββββββββ
β Kraken Exchange β
β (WebSocket + REST) β
ββββββββββββββββββββββββ
# 1. Clone the repository
git clone https://github.com/LeonelPerz/btc-ltp-service
cd btc-ltp-service
# 2. Start the service stack
docker-compose up -d
# 3. Test the API
curl http://localhost:8080/health
curl "http://localhost:8080/api/v1/ltp?pair=BTC/USD"
# 4. View Swagger documentation
open http://localhost:8080/docs# 1. Install dependencies
go mod download
# 2. Configure environment
cp env.example .env
export CACHE_BACKEND=memory
export PORT=8080
# 3. Run the service
go run cmd/api/main.go
# 4. With Redis (optional)
docker-compose up redis -d
export CACHE_BACKEND=redis
go run cmd/api/main.goCurrent Coverage: 31.1% overall
- Cache Package: 73.3%
- Kraken Package: 80.9%
- Config Package: 27.1%
- Exchange Package: 77.4%
- Cache eviction mechanisms - Automatic and manual cleanup of expired entries
- TTL (Time To Live) validation - Edge cases including zero, negative, and extreme values
- Trading pair validation - Format validation and known pair verification
- Concurrent cache operations - Thread-safe operations with race detection
- Memory cleanup and optimization - Efficient eviction under memory pressure
- Error handling and edge cases - Comprehensive error scenarios
- Resilience and fallback mechanisms - WebSocket to REST API fallback
# Run all tests with coverage
go test -cover ./...
# Generate detailed coverage report
./scripts/coverage-report.sh
# View HTML coverage report
open reports/coverage/coverage.htmlLast updated: 2025-09-24 15:56:00 UTC
go test -v ./internal/infrastructure/repositories/cache/... go test -v ./internal/infrastructure/exchange/kraken/... go test -v ./internal/infrastructure/config/...
go test -race ./internal/infrastructure/repositories/cache/... go test -race ./internal/infrastructure/exchange/kraken/... go test -race ./internal/infrastructure/config/...
- TTL-based eviction with different expiration times
- Partial eviction scenarios (some expired, some valid)
- Complete cache cleanup
- Auto-eviction during Set operations
- Concurrent eviction under memory pressure
- Zero TTL (immediate expiry)
- Negative TTL (pre-expired items)
- Microsecond precision TTL
- Very long TTL (365+ days)
- TTL behavior during concurrent access
- Valid major pairs (BTC/USD, ETH/USD, etc.)
- Case insensitive validation
- Format validation (BASE/QUOTE pattern)
- Unknown pair rejection
- Whitespace and malformed input handling
Our CI/CD pipeline enforces these coverage thresholds:
- π― Critical Packages: 70%+ (Cache, Kraken)
- Local Development:
http://localhost:8080 - Docker:
http://localhost:8080
The service supports optional API-key based authentication that can be enabled via configuration:
Default State: Authentication is disabled by default
Toggle Method: Set AUTH_ENABLED=true and AUTH_API_KEY=your-secret-key environment variables
Authenticated Endpoints: All /api/v1/* endpoints when auth is enabled
Always Unauthenticated: /health, /ready, /metrics, /swagger/, /docs
Usage Example:
# Enable authentication
export AUTH_ENABLED=true
export AUTH_API_KEY=mi-clave-secreta-2024
# Make authenticated requests
curl -H "X-API-Key: mi-clave-secreta-2024" "http://localhost:8080/api/v1/ltp?pair=BTC/USD"
# These endpoints work without authentication even when auth is enabled
curl http://localhost:8080/health
curl http://localhost:8080/readyConfiguration:
auth:
enabled: false # Toggle authentication
api_key: "" # Your API key (set via environment)
header_name: "X-API-Key" # Header name for API key
unauth_paths: # Paths exempt from authentication
- "/health"
- "/ready"
- "/metrics"
- "/swagger/"
- "/docs"GET /api/v1/ltp?pair={pairs}Description: Retrieves the latest traded prices for specified cryptocurrency pairs.
Query Parameters:
pair(optional): Comma-separated list of trading pairs (e.g.,BTC/USD,ETH/USD)- If empty, returns all supported pairs
Response (200 OK):
{
"ltp": [
{
"pair": "BTC/USD",
"amount": 50123.45
},
{
"pair": "ETH/USD",
"amount": 3456.78
}
]
}Partial Success (206 Partial Content):
{
"ltp": [
{
"pair": "BTC/USD",
"amount": 50123.45
}
],
"errors": [
{
"pair": "INVALID/PAIR",
"error": "Failed to fetch price",
"code": "PRICE_FETCH_ERROR",
"message": "Unsupported trading pair"
}
]
}Examples:
# All supported pairs
curl "http://localhost:8080/api/v1/ltp"
# Single pair
curl "http://localhost:8080/api/v1/ltp?pair=BTC/USD"
# Multiple pairs
curl "http://localhost:8080/api/v1/ltp?pair=BTC/USD,ETH/USD,BTC/EUR"POST /api/v1/ltp/refresh?pairs={pairs}Description: Manually refreshes cached prices for specified pairs.
Query Parameters:
pairs(required): Comma-separated list of trading pairs
Response (200 OK):
{
"message": "Prices refreshed successfully",
"pairs": ["BTC/USD", "ETH/USD"]
}Example:
curl -X POST "http://localhost:8080/api/v1/ltp/refresh?pairs=BTC/USD,ETH/USD"GET /api/v1/ltp/cachedDescription: Returns all prices currently stored in cache (for debugging/monitoring).
Response (200 OK):
{
"ltp": [
{
"pair": "BTC/USD",
"amount": 50123.45
}
]
}GET /healthDescription: Basic service health check.
Response (200 OK):
{
"status": "healthy",
"timestamp": "2024-01-01T12:00:00Z",
"services": {
"service": "running"
}
}GET /readyDescription: Readiness probe that validates dependencies (cache, external APIs).
Response (200 OK):
{
"status": "ready",
"timestamp": "2024-01-01T12:00:00Z",
"services": {
"cache": "ready",
"service": "ready"
}
}Response (503 Service Unavailable):
{
"status": "unhealthy",
"timestamp": "2024-01-01T12:00:00Z",
"services": {
"cache": "error: connection refused",
"service": "ready"
}
}GET /metricsDescription: Prometheus-compatible metrics endpoint.
Content-Type: text/plain
The service supports the following cryptocurrency pairs by default:
| Pair | Description |
|---|---|
| BTC/USD | Bitcoin to US Dollar |
| BTC/EUR | Bitcoin to Euro |
| BTC/CHF | Bitcoin to Swiss Franc |
| ETH/USD | Ethereum to US Dollar |
| LTC/USD | Litecoin to US Dollar |
| XRP/USD | Ripple to US Dollar |
Configurable: Additional pairs can be configured via the SUPPORTED_PAIRS environment variable.
| Variable | Default | Description |
|---|---|---|
| SERVER | ||
PORT |
8080 |
HTTP server port |
SHUTDOWN_TIMEOUT |
30s |
Graceful shutdown timeout |
| CACHE | ||
CACHE_BACKEND |
memory |
Cache backend: memory or redis |
CACHE_TTL |
30s |
Cache TTL duration |
REDIS_ADDR |
localhost:6379 |
Redis server address |
REDIS_PASSWORD |
Redis password (if required) | |
REDIS_DB |
0 |
Redis database number |
| BUSINESS | ||
SUPPORTED_PAIRS |
BTC/USD,ETH/USD,LTC/USD,XRP/USD |
Supported trading pairs |
| RATE LIMITING | ||
RATE_LIMIT_ENABLED |
true |
Enable/disable rate limiting |
RATE_LIMIT_CAPACITY |
100 |
Requests per bucket |
RATE_LIMIT_REFILL_RATE |
10 |
Refill rate per second |
| LOGGING | ||
LOG_LEVEL |
info |
Log level: debug, info, warn, error |
LOG_FORMAT |
json |
Log format: json or text |
| KRAKEN API | ||
KRAKEN_TIMEOUT |
10s |
HTTP client timeout |
KRAKEN_REQUEST_TIMEOUT |
3s |
Per-request timeout |
KRAKEN_FALLBACK_TIMEOUT |
15s |
WebSocket timeout |
KRAKEN_MAX_RETRIES |
3 |
Retry attempts |
The service implements a robust hierarchical configuration system with fail-fast validation:
1. Default Values (in code)
β (overridden by)
2. Base config.yaml
β (overridden by)
3. Environment-specific config.{env}.yaml
β (overridden by)
4. Environment Variables (highest priority)
| File | Purpose | Description |
|---|---|---|
| Base Configuration | ||
config.yaml |
Production default | Base configuration for all environments |
config.production.yaml |
Production env | Optimized settings for production deployment |
config.demo-precedence.yaml |
Precedence demo | Demonstrates ENV override behavior |
| Testing & Validation | ||
config.test-bad-ttl.yaml |
TTL validation | Contains invalid TTL values for testing |
config.test-invalid-types.yaml |
Type validation | Invalid data types for parsing tests |
config.test-zero-values.yaml |
Zero value detection | Explicit zero values that should fail |
config.explicit-zero.yaml |
Explicit zeros | Zero values with units (0s, 0ms) |
config.test-missing-units.yaml |
Unit validation | Numbers without time units |
| Environment Files | ||
demo.env |
ENV variables demo | Sample environment variable overrides |
Base YAML Configuration:
# configs/config.demo-precedence.yaml
server:
port: 9000 # Will be overridden by ENV
cache:
backend: redis # Will be overridden by ENV
ttl: 60s # Will be overridden by ENV
logging:
level: debug # Will be overridden by ENVEnvironment Override:
# These ENV vars override YAML values
export PORT=8080 # Overrides port: 9000
export CACHE_BACKEND=memory # Overrides backend: redis
export CACHE_TTL=30s # Overrides ttl: 60s
export LOG_LEVEL=info # Overrides level: debug
go run cmd/api/main.go -config configs/config.demo-precedence.yaml
# Result: Uses port=8080, backend=memory, ttl=30s, level=infoThe service implements comprehensive validation that fails fast on startup:
Bad TTL Detection:
# β These will fail immediately on startup:
CACHE_TTL=50ms go run cmd/api/main.go
# Error: "TTL too short: 50ms, minimum 100ms (causes excessive cache churn)"
CACHE_TTL=25h go run cmd/api/main.go
# Error: "TTL too long: 25h, maximum 24h (stale data risk)"Unknown Trading Pairs Detection:
# β This will fail immediately:
SUPPORTED_PAIRS="BTC/USD,DOGE/MOON" go run cmd/api/main.go
# Error: "unknown trading pairs: [DOGE/MOON], supported pairs: [BTC/USD, ETH/USD, ...]"Environment Detection: Automatically detects environment via ENVIRONMENT variable or falls back to development.
# 1. Use default configuration
go run cmd/api/main.go
# 2. Use specific config file
go run cmd/api/main.go -config configs/config.production.yaml
# 3. Override with environment variables
PORT=9000 CACHE_TTL=60s go run cmd/api/main.go
# 4. Load from environment file
source configs/demo.env && go run cmd/api/main.go
# 5. Test fail-fast validation
go run cmd/api/main.go -config configs/config.test-bad-ttl.yamlThe service includes automated scripts for testing configuration validation:
# Test all configuration validation scenarios
./scripts/demo-config-validation.sh
# Test invalid data types handling
./scripts/demo-invalid-types.sh
# Manual testing examples:
CACHE_TTL=10ms go run cmd/api/main.go # β TTL too short
SUPPORTED_PAIRS="FAKE/COIN" go run cmd/api/main.go # β Unknown pair
PORT=8080 LOG_LEVEL=debug go run cmd/api/main.go # β
Valid override| Validation Type | Examples | Error Behavior |
|---|---|---|
| TTL Validation | 50ms, 25h, invalid |
Fails before service start |
| Trading Pairs | DOGE/MOON, INVALID |
Lists valid alternatives |
| Data Types | "abc" for numbers |
Viper parsing error |
| Missing Units | 30 instead of 30s |
Duration parsing error |
| Zero Values | ttl: 0, port: 0 |
Detected as parsing errors |
Key Benefits:
- π Fail-Fast: Invalid configs prevent service startup
- π Specific Errors: Clear error messages with suggestions
- π‘οΈ Multiple Layers: Viper parsing + Custom validation + Business rules
- π Helpful Messages: Shows valid alternatives and reasoning
For complete validation examples and testing, see docs/CONFIG-VALIDATION.md.
The service exposes 30+ metrics across different categories:
btc_ltp_http_requests_total- Total HTTP requests by method/path/statusbtc_ltp_http_request_duration_seconds- Request duration histogrambtc_ltp_http_request_size_bytes- Request size histogrambtc_ltp_http_response_size_bytes- Response size histogram
btc_ltp_cache_operations_total- Cache operations counter (hit/miss/error)btc_ltp_cache_keys- Number of keys in cachebtc_ltp_cache_hits_total- Cache hits counterbtc_ltp_cache_misses_total- Cache misses counter
btc_ltp_external_api_requests_total- External API requestsbtc_ltp_external_api_request_duration_seconds- External API latencybtc_ltp_external_api_retries_total- Retry attempts
btc_ltp_price_requests_total- Requests per trading pairbtc_ltp_current_prices- Current prices gaugebtc_ltp_price_age_seconds- Price age in cache
btc_ltp_rate_limit_requests_total- Rate limit decisionsbtc_ltp_rate_limit_tokens_remaining- Remaining tokens per client
All logs are structured in JSON format with contextual information:
{
"timestamp": "2024-01-01T12:00:00Z",
"level": "INFO",
"message": "HTTP request processed",
"request_id": "req-abc123",
"service": "btc-ltp-service",
"version": "1.0.0",
"fields": {
"http_method": "GET",
"http_path": "/api/v1/ltp",
"http_status_code": 200,
"duration_ms": 45.2,
"cache_hit": true,
"pairs_count": 3
}
}The service includes comprehensive benchmarking scripts:
# Run all benchmarks
./benchmarks/scripts/run_benchmarks.sh
# Cache effectiveness test
BASE_URL=http://localhost:8080 k6 run benchmarks/k6/cache_effectiveness.js
# Load testing
BASE_URL=http://localhost:8080 k6 run benchmarks/k6/load_test.js
# Stress testing
BASE_URL=http://localhost:8080 k6 run benchmarks/k6/stress_test.jsbenchmarks/benchmark-analysis.md.
| Metric | Target | Description |
|---|---|---|
| Cache Hit Rate | 85%+ | Under normal load |
| Response Time | <50ms | With cache hit |
| Throughput | 300+ RPS | Concurrent users |
| Availability | 99.9% | Service uptime |
# Run all tests
go test ./...
# With race detection
go test -race ./...
# With coverage
go test -cover ./...
# Verbose output
go test -v ./...# Basic functionality
curl "http://localhost:8080/api/v1/ltp?pair=BTC/USD"
# Multiple pairs
curl "http://localhost:8080/api/v1/ltp?pair=BTC/USD,ETH/USD"
# Health checks
curl http://localhost:8080/health
curl http://localhost:8080/ready
# Metrics
curl http://localhost:8080/metrics
# Cache inspection
curl http://localhost:8080/api/v1/ltp/cached- Rate Limiting: Token bucket algorithm prevents abuse
- Input Validation: Comprehensive request validation
- Docker Security: Non-root user, minimal attack surface
- Error Handling: No sensitive information leakage
- CORS: Configurable cross-origin policies
- Run with non-root user in production
- Use HTTPS in production environments
- Configure rate limiting based on expected load
- Monitor metrics for anomalous patterns
- Keep dependencies updated regularly
version: '3.8'
services:
btc-ltp-service:
build: .
ports:
- "8080:8080"
environment:
- CACHE_BACKEND=redis
- REDIS_ADDR=redis:6379
depends_on:
- redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"- Environment Variables: Use secrets management for sensitive data
- Resource Limits: Set appropriate CPU/memory limits
- Health Checks: Configure container health checks
- Logging: Centralize log aggregation
- Monitoring: Set up Prometheus + Grafana dashboards
- Alerting: Configure alerts for critical metrics
btc-ltp-service/
βββ cmd/
β βββ api/ # Application entry point
βββ internal/
β βββ application/ # Application layer (DTOs, services)
β βββ domain/ # Domain layer (entities, interfaces)
β βββ infrastructure/ # Infrastructure layer (external concerns)
β βββ config/ # Configuration management
β βββ exchange/ # Exchange clients (Kraken)
β βββ logging/ # Structured logging
β βββ metrics/ # Prometheus metrics
β βββ repositories/ # Data access (cache)
β βββ web/ # HTTP layer (handlers, middleware)
βββ configs/ # Configuration files & validation examples
β βββ config.yaml # Base configuration
β βββ config.production.yaml # Production environment
β βββ config.demo-precedence.yaml # Precedence demonstration
β βββ config.test-*.yaml # Validation test cases
β βββ demo.env # Environment variables example
βββ scripts/ # Configuration demo & validation scripts
β βββ demo-config-validation.sh # Comprehensive validation demo
β βββ demo-invalid-types.sh # Invalid data types demo
βββ benchmarks/ # Load testing scripts
βββ docs/ # Documentation
β βββ CONFIG-VALIDATION.md # Configuration validation guide
βββ docker-compose.yml # Development stack
| Code | Description | HTTP Status |
|---|---|---|
INVALID_PARAMETER |
Invalid request parameters | 400 |
UNSUPPORTED_PAIR |
Trading pair not supported | 400 |
PRICE_FETCH_ERROR |
Failed to fetch price data | 500 |
CACHE_ERROR |
Cache operation failed | 500 |
ALL_PRICES_FAILED |
All price requests failed | 500 |
RATE_LIMIT_EXCEEDED |
Rate limit exceeded | 429 |
ENCODING_ERROR |
Response encoding failed | 500 |
This project is licensed under the MIT License - see the LICENSE file for details.
- Swagger/OpenAPI Documentation (when running)
- Prometheus Metrics (when running)
- Kraken API Documentation
- Go Documentation