Architecture Overview
The local development environment uses Docker Compose to orchestrate three services:Environment Configuration
Backend Variables
The backend reads configuration from environment variables defined indocker-compose.yml. You can override any of these by creating a .env file in the project root:
After creating or modifying
.env, restart services: docker compose up -dBackend Environment Variables Reference
| Variable | Required | Default | Description |
|---|---|---|---|
DB_HOST | Yes | postgres | PostgreSQL hostname (use service name in Docker Compose) |
DB_PORT | Yes | 5432 | PostgreSQL port |
DB_NAME | Yes | urlshortener | Database name |
DB_USERNAME | Yes | postgres | Database user |
DB_PASSWORD | Yes | changeme | Database password |
JWT_SECRET | Yes | (default provided) | JWT signing key (min. 32 characters) |
JWT_EXPIRATION_MS | No | 86400000 | JWT token lifetime in milliseconds (24h default) |
SERVER_PORT | No | 8080 | Backend server port |
APP_BASE_URL | Yes | http://localhost:8080 | Base URL for generating short links |
CORS_ALLOWED_ORIGINS | Yes | (localhost variants) | Comma-separated list of allowed origins |
Frontend Variables
The frontend uses Vite, which embeds environment variables at build time. The backend API URL is configured viaVITE_API_BASE_URL:
Hot Reload & Development Workflow
Backend Hot Reload
The backend Dockerfile uses a multi-stage build that compiles the full JAR. For faster development:Option 1: Use Spring Boot DevTools (Recommended)
- Stop the Docker backend:
docker compose stop backend - Run the backend directly with Gradle:
Option 2: Volume Mount (Advanced)
Mount your local source code into the container for quicker rebuilds:docker-compose.override.yml
Frontend Hot Reload
For frontend development with instant refresh:- Stop the Docker frontend:
docker compose stop frontend - Run Vite dev server locally:
http://localhost:5173 with HMR (Hot Module Replacement).
Make sure your
.env.local file has:Debugging
Backend Debugging with IntelliJ IDEA
Enable debug port in docker-compose
Create Restart:
docker-compose.override.yml:docker compose up -d backendConfigure IntelliJ Remote Debug
- Go to Run → Edit Configurations
- Click + → Remote JVM Debug
- Set Host:
localhost, Port:5005 - Click OK
Backend Debugging with VS Code
Add to.vscode/launch.json:
Frontend Debugging
Use browser DevTools or VS Code’s built-in debugger:.vscode/launch.json
Database Access
Connect with psql
Connect with GUI Tools
Use any PostgreSQL client with these credentials:| Setting | Value |
|---|---|
| Host | localhost |
| Port | 5432 |
| Database | urlshortener |
| Username | postgres |
| Password | changeme |
Reset Database
To start fresh with a clean database:Logs & Monitoring
View Logs
Application Logs
Backend logging is configured inapplication.yml:
TRACE for even more verbose output during debugging.
Testing
Backend Tests
Frontend Tests
Common Development Tasks
Add a Database Migration
The app uses Hibernate’sddl-auto: update in development, which automatically creates/updates tables. For production, you should use Flyway or Liquibase.
Change Backend Port
Editdocker-compose.yml:
VITE_API_BASE_URL and rebuild the frontend!
Enable CORS for New Origin
Add toCORS_ALLOWED_ORIGINS in docker-compose.yml:
Performance Optimization
Spring Boot JVM Settings
The backend Dockerfile includes optimized JVM flags:UseContainerSupport: Detect container memory limitsMaxRAMPercentage=75.0: Use 75% of available container memoryjava.security.egd: Faster random number generation
PostgreSQL Connection Pool
Adjust HikariCP settings inapplication.yml:
Troubleshooting
Backend exits with 'Cannot connect to database'
Backend exits with 'Cannot connect to database'
PostgreSQL may not be ready when the backend starts. The compose file includes a
depends_on health check, but you can also manually check:Frontend shows blank page
Frontend shows blank page
Check the browser console for errors. Common causes:
-
VITE_API_BASE_URL mismatch: The frontend was built with wrong API URL
- Verify in browser DevTools → Network tab
- Rebuild:
docker compose up -d --build frontend
-
CORS errors: Backend doesn’t allow the frontend origin
- Add to
CORS_ALLOWED_ORIGINSin docker-compose.yml - Restart backend:
docker compose restart backend
- Add to
Changes not reflected after rebuild
Changes not reflected after rebuild
Docker may be using cached layers:For frontend, also clear browser cache (Cmd+Shift+R / Ctrl+Shift+R).
Port 8080/80 already in use
Port 8080/80 already in use
Find and stop the conflicting process:Or change the port in
docker-compose.yml.'gradlew: Permission denied' error
'gradlew: Permission denied' error
The Gradle wrapper needs execute permissions:
Next Steps
Deploy to AWS
Deploy to production with ECS Fargate, RDS, and ALB
Architecture
Learn about the system design and business rules