A lightweight, fast API gateway for microservice applications
LSG (Lightweight Service Gateway) is a personal project exploring the development of a modern, reactive API gateway built with Spring Boot WebFlux. It's designed to route and manage traffic to microservices with minimal overhead, using a simple YAML file as the single source of truth for service configuration.
- Reactive & Non-blocking: Built on Spring WebFlux for high-performance, non-blocking I/O
- YAML-based Service Configuration: Define your backend services with a simple, declarative configuration file
- Hot Reload: Configuration changes are detected and applied without restarting the gateway
- Request Filtering: Control allowed HTTP methods per service
- Header Manipulation: Add, remove, or replace headers on requests
- Request Size Limiting: Configure maximum request sizes per service
- Full Observability Stack:
- Metrics: Prometheus integration with Micrometer
- Tracing: Distributed tracing with OpenTelemetry and Jaeger
- Dashboards: Grafana for visualization
- Docker Compose Support: Ready-to-use observability infrastructure
LSG uses a single YAML file (services.yml) as the source of truth for all service routing configuration. This architectural decision comes with trade-offs:
| Advantage | Description |
|---|---|
| Simplicity | Easy to read, write, and understand—no database or complex setup required |
| Hot Reload Support | Changes to services.yml are applied without restarting the gateway |
| Version Control Friendly | Configuration changes are tracked in Git with full history and diff support |
| Portability | Easy to copy, share, and replicate environments |
| No External Dependencies | No need for a database, config server, or external service registry |
| Fast Startup | Configuration is loaded at startup with no network calls |
| GitOps Compatible | Fits naturally into GitOps workflows and CI/CD pipelines |
| Human Readable | Non-developers can understand and review configurations |
| Disadvantage | Description |
|---|---|
| Scalability Limits | Not ideal for managing hundreds of services |
| No Dynamic Discovery | Services must be manually defined; no auto-discovery from service registries |
| Single Point of Configuration | All routing logic in one file can become unwieldy |
| No Built-in Validation UI | Syntax errors are caught at load time, not during editing |
| Environment Management | Requires separate files or templating for different environments |
- Small to medium-sized microservice deployments
- Projects where you want simple, file-based configuration with live updates
- Teams comfortable with GitOps and infrastructure-as-code
- Learning and experimentation environments
| Component | Technology |
|---|---|
| Language | Java 25 |
| Framework | Spring Boot 4.0.2 |
| Cloud | Spring Cloud 2025.1.0 |
| Reactive | Spring WebFlux |
| HTTP Client | WebClient |
| Metrics | Micrometer + Prometheus |
| Tracing | OpenTelemetry + Jaeger |
| Visualization | Grafana |
| Build Tool | Maven |
- Java 25+
- Maven 3.9+
- Docker & Docker Compose (for observability stack)
-
Clone the repository
git clone https://github.com/RyanKHLI/LSG.git cd LSG -
Build the project
./mvnw clean install
-
Run the application
./mvnw spring-boot:run
The gateway will start on
http://localhost:8080
docker-compose up -dThis will start:
- Prometheus on port
9090- Metrics collection - Jaeger on port
16686- Distributed tracing UI - Grafana on port
3000- Dashboards (default credentials: admin/admin)
Define your backend services in src/main/resources/services.yml:
- name: myService
host: https://api.example.com
endpoint: /api/v1/resource
visibility: public
filters:
allowedMethods:
- GET
- POST
headers:
add:
X-Gateway: LSG
remove:
- Host
replace:
Content-Type: application/json
maxRequestSize: 10KBHot Reload: Any changes to
services.ymlare automatically detected and applied—no restart required!
| Property | Description | Example |
|---|---|---|
name |
Service identifier used in routing | userService |
host |
Backend service base URL | https://api.example.com |
endpoint |
Backend endpoint path | /api/v1/users |
visibility |
Service visibility (public/private) |
public |
filters.allowedMethods |
List of allowed HTTP methods | [GET, POST] |
filters.headers.add |
Headers to add to requests | X-Gateway: LSG |
filters.headers.remove |
Headers to remove from requests | [Host] |
filters.headers.replace |
Headers to replace | Content-Type: application/json |
filters.maxRequestSize |
Maximum allowed request body size | 10KB |
spring.application.name=LSG
server.address=0.0.0.0
server.port=8080
# Metrics & Tracing
management.endpoints.web.exposure.include=health,info,metrics,prometheus
management.tracing.sampling.probability=1
management.tracing.propagation.type=w3c
management.opentelemetry.tracing.export.otlp.endpoint=http://localhost:4318/v1/tracesAccess Prometheus metrics at: http://localhost:8080/actuator/prometheus
Available endpoints:
/actuator/health- Health check/actuator/info- Application info/actuator/metrics- Metrics overview/actuator/prometheus- Prometheus-formatted metrics
All requests are traced with OpenTelemetry and can be visualized in Jaeger at http://localhost:16686.
Grafana is pre-configured with Prometheus as a data source. Access it at http://localhost:3000.
LSG/
├── src/
│ ├── main/
│ │ ├── java/org/rayen/ # Java source code
│ │ └── resources/
│ │ ├── application.properties
│ │ ├── application-dev.properties
│ │ ├── services.yml # Service definitions (SOURCE OF TRUTH)
│ │ └── logback-spring.xml
│ └── test/ # Test files
├── observability/ # Observability configurations
│ └── prometheus/config/ # Prometheus config
├── docker-compose.yaml # Docker services
├── pom.xml # Maven configuration
└── README.md
./mvnw spring-boot:run -Dspring-boot.run.profiles=dev./mvnw testAs this is a personal project, here are some features I'm considering exploring:
- Rate limiting per service
- Circuit breaker integration
- Authentication/Authorization filters
- Service health checks
- Load balancing across multiple instances
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
This is a personal project, but suggestions and feedback are welcome! Feel free to open an issue to discuss ideas or report bugs.
A personal project by @RyanKHLI