Deployment & Infrastructure Architecture
Deployment Topology
(Source Code)"] DocsBranch["docs branch
(GH Pages output)"] PRs["Pull Requests
(Reviews)"] end MainBranch -->|Push to origin/main| Actions subgraph Actions["GitHub Actions (CI/CD Pipelines)"] Build["Build & Test Workflow
(deploy-backend.yml)
1. Checkout code
2. Run Maven build
3. Run tests (65+)
4. Build Docker image
5. Push to GHCR
6. Deploy to Koyeb"] Docs["Docs Generation Workflow
(docs-pipeline.yml + docs-coverage-deploy.yml)
1. Extract OpenAPI spec
2. Convert Markdown β HTML
3. Generate Redoc HTML
4. Collect coverage
5. Commit to docs branch
6. GitHub Pages auto-sync"] end Build -->|GHCR Image
ghcr.io/keglev/...| Koyeb Docs -->|Generated HTML
docs branch| Pages Koyeb["Koyeb
Container Service
(Production)"] Pages["GitHub Pages
(docs branch)
https://Keglev..."] Koyeb -->|JDBC Connection| Neon Neon["Neon PostgreSQL 17.5
(Serverless Database)
- Auto-backups
- Connection pooling
- Failover support"] style GitHub fill:#f9f9f9 style Actions fill:#e3f2fd style Koyeb fill:#fff3e0 style Pages fill:#e8f5e9 style Neon fill:#fce4ec
CI/CD Pipeline Details
Build
& Deploy Workflow
(deploy-backend.yml)
Trigger Events: - Push to
main branch - Pull request creation -
Manual trigger (workflow_dispatch)
Pipeline Stages:
- Set up JDK 17
- Cache Maven dependencies
- Verify build environment"] B -->|Details| B1["- Run Maven clean package
- Compile all Java source code
- Skip tests in this stage
- Generate JAR file"] C -->|Details| C1["- Run 65+ unit tests
- Tests use H2 in-memory database
- Generate coverage reports (JaCoCo)
- Fail pipeline if tests don't pass"] D -->|Details| D1["- Read Dockerfile from repository
- Build image based on Dockerfile
- Tag as ghcr.io/keglev/stockease latest
- Tag as ghcr.io/keglev/stockease commit-sha
- Generate SBOM"] E -->|Details| E1["- Authenticate with GHCR
- Push tagged images to GHCR
- Make images available for deployment
- Store in ghcr.io/keglev/stockease"] F -->|Details| F1["- Get Koyeb API token from secrets
- Trigger Koyeb deployment
- Pull latest image from GHCR
- Perform blue-green deployment
- Health checks (retry up to 5 times)
- Rollback if health check fails"] G -->|Details| G1["- Verify deployment status
- Check health endpoint /health
- Log deployment results
- Notify on success/failure"] style A fill:#e3f2fd style B fill:#e3f2fd style C fill:#e3f2fd style D fill:#e3f2fd style E fill:#e3f2fd style F fill:#e3f2fd style G fill:#c8e6c9
Documentation
Pipeline (docs-pipeline.yml +
docs-coverage-deploy.yml)
Trigger Events: - Push to
main when /backend/docs/
changes - Manual trigger
Pipeline Stages:
- Start Spring Boot server
- Fetch OpenAPI spec from /v3/api-docs
- Validate OpenAPI spec
- Save to docs/api/openapi/openapi.json"] B -->|Details| B1["- Install Redoc CLI
- Read OpenAPI spec
- Generate interactive HTML documentation
- Output to docs/api/redoc/index.html
- Optimize for web"] C -->|Details| C1["- Install pandoc
- For each .md file in docs/architecture/:
* Convert to HTML
* Apply styling
* Output to docs/architecture/*.html
- Convert docs/index.md to docs/index.html
- Generate table of contents"] D -->|Details| D1["- Run Maven test with JaCoCo
- Generate coverage report
- Copy to docs/coverage/
- Generate index.html for coverage dashboard
- Calculate coverage percentage"] E -->|Details| E1["- Switch to docs branch
- Remove old generated files
- Copy all new HTML files
- Commit with auto-generated documentation
- Push to origin/docs
- GitHub Pages auto-publishes"] F -->|Details| F1["- Remove temporary files
- Clean build artifacts
- Log completion"] style A fill:#e3f2fd style B fill:#e3f2fd style C fill:#e3f2fd style D fill:#e3f2fd style E fill:#e3f2fd style F fill:#c8e6c9
Deployment Environments
Development Environment
- Branch: Any feature branch
- Triggered By: Manual trigger or PR
- Database: H2 in-memory (testing only)
- Deployment: Skipped
- Testing: Full suite (65+ tests)
Staging Environment
- Branch: develop (if used)
- Deployment Target: Separate Koyeb service
- Database: PostgreSQL test instance
- Testing: Full test suite + smoke tests
- Duration: 10-15 minutes
Production Environment
- Branch: main
- Deployment Target: Koyeb production service
- Database: Neon PostgreSQL (production)
- URL: https://stockease-backend-production.koyeb.app
- Testing: Full test suite + health checks
- Duration: 3-5 minutes
- Rollback: Automatic if health checks fail
Koyeb Deployment Configuration
Service Details
Service Name: stockease-backend-production
Status: HEALTHY
Runtime: Docker (custom image)
Region: US (Auto)
Replicas: 1-2 (auto-scaling)
Domain: stockease-backend-production.koyeb.app
Environment Variables:
SPRING_PROFILES_ACTIVE: production
DB_HOST: [Neon endpoint]
DB_PORT: 5432
DB_NAME: stockease
DB_USER: [from secrets]
DB_PASSWORD: [from secrets]
JWT_SECRET: [from secrets]
JAVA_OPTS: -Xmx512m -Xms256m
Port Mapping:
Container Port: 8080
Public Port: 443 (HTTPS)
Protocol: HTTP2
Health Check:
Endpoint: /health
Interval: 30 seconds
Timeout: 5 seconds
Consecutive Failures: 3
Consecutive Successes: 1Auto-Scaling Configuration
Min Replicas: 1
Max Replicas: 2
Target CPU: 70%
Target Memory: 80%
Scale Up Delay: 60 seconds
Scale Down Delay: 300 secondsDatabase Management (Neon PostgreSQL)
Connection Details
Host: [neon-project].neon.tech
Port: 5432
Database: stockease
SSL Mode: require
Connection Pooling: Enabled (connection limit: 100)
Automated Backups
- Frequency: Automatic daily
- Retention: 7 days
- Backup Type: Full backup
- Recovery: Point-in-time restore available
Database Migrations (Flyway)
Migration Files (in
src/main/resources/db/migration/):
V1__init_schema.sql
βββ CREATE TABLE users
β βββ id (UUID, PK)
β βββ username (VARCHAR, UNIQUE)
β βββ password (VARCHAR, BCrypt)
β βββ role (VARCHAR)
β βββ created_at (TIMESTAMP)
β βββ updated_at (TIMESTAMP)
β
βββ CREATE TABLE products
βββ id (UUID, PK)
βββ name (VARCHAR)
βββ description (TEXT)
βββ price (DECIMAL)
βββ quantity (INTEGER)
βββ sku (VARCHAR, UNIQUE)
βββ category (VARCHAR)
βββ created_at (TIMESTAMP)
βββ updated_at (TIMESTAMP)
βββ created_by (UUID, FK β users)
V2__add_indexes.sql
βββ CREATE INDEX idx_products_sku
βββ CREATE INDEX idx_products_category
βββ CREATE INDEX idx_users_username
βββ CREATE INDEX idx_products_created_by
V3__seed_data.sql
βββ INSERT admin user (admin/admin123)
βββ INSERT regular user (user/user123)
βββ INSERT sample products
βββ Uses DB-agnostic existence check for H2 compatibility
Migrations Overview:
Migration Files:
- products table"] V2 -->|Adds| V2A["- idx_products_sku
- idx_products_category
- idx_users_username
- idx_products_created_by"] V3 -->|Inserts| V3A["- admin user (admin/admin123)
- regular user (user/user123)
- sample products
- H2 compatibility checks"] style V1 fill:#e3f2fd style V2 fill:#e3f2fd style V3 fill:#c8e6c9
Migration Execution:
Application Startup
βββ Spring Boot loads
βββ Flyway initializes
βββ Checks flyway_schema_history table
βββ Identifies new migrations
βββ Executes migrations in order
βββ Updates schema version
βββ Application proceeds with data access
Containerization
Dockerfile
# Multi-stage build for optimization
FROM eclipse-temurin:17-jdk-alpine AS builder
WORKDIR /app
COPY mvnw .
COPY pom.xml .
COPY src src
# Build application
RUN ./mvnw clean package -DskipTests
# Runtime stage
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
# Copy JAR from builder
COPY --from=builder /app/target/stockease-backend-*.jar app.jar
# Health check
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health || exit 1
# Expose port
EXPOSE 8080
# Run application
ENTRYPOINT ["java", "-jar", "app.jar"]Image Details: - Base Image: eclipse-temurin:17-jre-alpine (122MB) - Final Size: ~350MB (with JAR and dependencies) - Build Time: ~2 minutes - Startup Time: ~8-10 seconds
Image Registry (GHCR)
Registry: ghcr.io/keglev/stockease
Authentication: GitHub PAT (Personal Access Token)
Image Tags:
- ghcr.io/keglev/stockease:latest (always latest build)
- ghcr.io/keglev/stockease:v1.0.0 (semantic versioning)
- ghcr.io/keglev/stockease:sha-abc123 (commit hash)
Monitoring & Observability
Health Checks
Endpoint:
GET /health
Response (when healthy):
{
"status": "UP",
"components": {
"db": {
"status": "UP",
"details": {
"database": "PostgreSQL",
"validationQuery": "isValid()"
}
},
"diskSpace": {
"status": "UP",
"details": {
"total": 10737418240,
"free": 5368709120,
"threshold": 10485760,
"exists": true
}
}
}
}Response (when unhealthy):
{
"status": "DOWN",
"components": {
"db": {
"status": "DOWN",
"details": {
"error": "Connection refused"
}
}
}
}Application Logs
Log Output (captured by Koyeb):
[2025-10-31 10:30:00] INFO o.s.b.StartupInfoLogger : Starting StockEaseApplication
[2025-10-31 10:30:01] INFO o.s.d.r.c.EnableJpaRepositoriesRegistrar : Scanning JPA repositories
[2025-10-31 10:30:02] INFO o.f.c.internal.license.VersionPrinter : Flyway Community Edition
[2025-10-31 10:30:02] INFO o.f.c.internal.database.base.DatabaseFactory : Database: PostgreSQL 17.5
[2025-10-31 10:30:02] INFO o.f.c.i.s.sql.PlaceholderReplacer : Locations: [classpath:db/migration]
[2025-10-31 10:30:02] INFO o.f.c.i.c.sql.SqlScriptExecutor : Successfully validated 3 migrations
[2025-10-31 10:30:02] INFO o.f.c.i.c.sql.SqlScriptExecutor : Current version of schema "public": 3
[2025-10-31 10:30:03] INFO o.s.s.web.DefaultSecurityFilterChain : Will secure any request
[2025-10-31 10:30:03] INFO o.s.b.w.e.tomcat.TomcatWebServer : Tomcat started on port(s): 8080
[2025-10-31 10:30:04] INFO o.s.b.StartupInfoLogger : Started StockEaseApplication in 4.123s
Metrics Monitoring
Tracked Metrics: - Request Count: Requests per minute - Response Time: Average, P50, P95, P99 - Error Rate: 4xx, 5xx errors - Database Connections: Active, idle, queued - Memory Usage: Heap, non-heap - CPU Usage: Container CPU %
Alerts (future): - Health check failures (trigger rollback) - High error rate (>5%) - Slow response times (>500ms avg) - Memory pressure (>85%) - Database connection pool exhaustion
Disaster Recovery
Backup Strategy
- Database: Automated daily backups (Neon)
- Code: Git repository with full history
- Configuration: Environment variables in GitHub Secrets
- Docker Images: Retained in GHCR
Recovery Procedures
If Deployment Fails: 1. CI pipeline detects failure 2. Health checks fail 3. Koyeb automatically rolls back to previous version 4. Notification sent to team 5. Review logs for root cause
If Database is Corrupted: 1. Determine recovery point from backups 2. Create database restore job 3. Test restore in staging environment 4. Point Koyeb to restored database 5. Verify application functionality
If Koyeb Service Goes Down: 1. Manual trigger of deployment pipeline 2. Redeploy from latest commit 3. Verify health checks pass 4. Monitor for stability
Performance Tuning
JVM Configuration
-Xmx512m # Max heap: 512MB
-Xms256m # Initial heap: 256MB
-XX:+UseG1GC # G1 garbage collection
-XX:MaxGCPauseMillis=200
Database Optimization
Connection Pool: HikariCP
Max Connections: 10
Idle Timeout: 600 seconds
Connection Timeout: 30 seconds
Caching (Future)
- Spring Cache abstraction
- Redis for session/data caching
- TTL: 1 hour for product data
Security in Deployment
Secrets Management
Environment Variables (GitHub Secrets):
- DB_PASSWORD
- JWT_SECRET
- GITHUB_TOKEN (for deployments)
Never Committed to Repository: - Database passwords - API keys - JWT secrets - Personal access tokens
Network Security
- HTTPS/TLS enforced
- CORS configured for frontend domain only
- WAF rules (via Koyeb/CloudFlare)
- DDoS protection enabled
Image Security
- No hardcoded secrets in Docker image
- Alpine Linux for minimal attack surface
- Regular base image updates
- SBOM (Software Bill of Materials) generated
Deployment Checklist
Before production deployment: - [ ] All tests passing (65+) - [ ] Code reviewed - [ ] Secrets configured in GitHub - [ ] Database migrations validated - [ ] Docker image built and tested - [ ] Health checks verified - [ ] CORS configured correctly - [ ] SSL certificates valid - [ ] Backups configured - [ ] Monitoring/alerting set up - [ ] Documentation updated - [ ] Rollback plan prepared
Related Documentation
Main Architecture Topics
- Architecture Overview - Business context and infrastructure decisions
- Backend Architecture - Application structure being deployed
- Service Layers - Layer-level considerations for deployment
- Security Architecture - Security requirements for production deployment
Architecture Decisions (ADRs)
- Database Choice - PostgreSQL for production, H2 for testing
- Validation Strategy - Validation in pre-production testing
Design Patterns & Practices
- Security Patterns - HTTPS/TLS, encryption, secure configuration
- Repository Pattern - Database connection strategies for production
Deployment Details
- CI/CD Pipeline - GitHub Actions for automated deployments
- Staging Configuration - Pre-production testing and verification
Related Frontend Docs
- Frontend Architecture - React deployment to Render
Document Version: 1.0
Last Updated: October 31, 2025
Status: Production Ready