Spring-Ready Python
Make your Python FastAPI app work seamlessly with Spring Boot ecosystem: Eureka, Config Server, Spring Boot Admin, and Prometheus.
Why This Exists
You have a Spring Boot microservices architecture with Eureka, Config Server, Spring Boot Admin, and Prometheus monitoring. You want to add a Python service but keep everything working together. This library makes that dead simple.
Features
✅ Eureka Service Registration - Automatic registration with heartbeat
✅ Config Server Integration - Load config from Spring Cloud Config with Eureka discovery
✅ Actuator Endpoints - /actuator/health, /actuator/info, /actuator/prometheus
✅ FastAPI Integration - Drop-in support for FastAPI apps
✅ Fail-Fast Behavior - Matches Spring Boot's startup failure handling
✅ Exponential Backoff Retry - Retry logic for Eureka and Config Server
✅ Zero Magic - Own implementation, no hidden dependencies
Installation
pip install spring-ready-python
Optional dependencies:
# For Config Server support
pip install spring-config-client-python
# For Prometheus metrics
pip install prometheus-client
Quick Start
from spring_ready import SpringReadyApp
from fastapi import FastAPI
# Create FastAPI app
app = FastAPI()
# Add Spring integration
spring_app = SpringReadyApp(app)
spring_app.start()
# Your routes
@app.get("/")
def read_root():
return {"message": "Hello from Spring-Ready Python!"}
# Run with uvicorn
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8080)
That's it. Your app now:
- Registers with Eureka
- Loads config from Config Server (discovered via Eureka)
- Exposes
/actuator/health,/actuator/info,/actuator/prometheus - Shows up in Spring Boot Admin
Configuration
Set via environment variables (matching Spring Boot conventions):
# Application
SPRING_APPLICATION_NAME=my-python-service
APP_PORT=8080
SPRING_PROFILES_ACTIVE=production
# Eureka
EUREKA_SERVER_URL=http://eureka:8761/eureka/
EUREKA_INSTANCE_IP=192.168.1.100 # Optional: custom IP for registration
EUREKA_INSTANCE_HOSTNAME=my-service.example.com # Optional: custom hostname
# Config Server (optional - will be discovered from Eureka)
CONFIG_SERVER_URI=http://config-server:8888
CONFIG_SERVER_USERNAME=admin
CONFIG_SERVER_PASSWORD=secret
Environment Variables Reference
| Variable | Description | Default | Example |
|---|---|---|---|
SPRING_APPLICATION_NAME |
Application name | python-service |
my-python-service |
APP_PORT |
Application port | 8080 |
8080 |
SPRING_PROFILES_ACTIVE |
Active profile | default |
production |
EUREKA_SERVER_URL |
Eureka server URL(s) | http://localhost:8761/eureka/ |
http://eureka:8761/eureka/ |
EUREKA_INSTANCE_IP |
Custom IP for registration | Auto-detected | 192.168.1.100 |
EUREKA_INSTANCE_HOSTNAME |
Custom hostname | Auto-detected | my-service.local |
EUREKA_INSTANCE_SECURE |
Register with HTTPS URLs | false |
true |
CONFIG_SERVER_URI |
Config Server URL | Discovered from Eureka | http://config:8888 |
CONFIG_SERVER_SERVICE_ID |
Config Server service ID | CONFIG-SERVER |
CONFIG-SERVER |
CONFIG_SERVER_USERNAME |
Config Server username | None | admin |
CONFIG_SERVER_PASSWORD |
Config Server password | None | secret |
Docker Example
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
ENV SPRING_APPLICATION_NAME=my-service
ENV EUREKA_SERVER_URL=http://eureka:8761/eureka/
ENV SPRING_PROFILES_ACTIVE=production
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]
# docker-compose.yml
services:
my-service:
build: .
environment:
- EUREKA_SERVER_URL=http://eureka:8761/eureka/
- SPRING_PROFILES_ACTIVE=production
ports:
- "8080:8080"
Advanced Usage
Custom Health Checks
from spring_ready import SpringReadyApp
spring_app = SpringReadyApp(app)
spring_app.start()
# Add custom health check
def check_database():
# Your database check logic
return database.is_connected()
spring_app.health_endpoint.add_check("database", check_database)
Service Discovery
# Find another service registered in Eureka
config_server_url = spring_app.service_discovery.get_service_url("CONFIG-SERVER")
# Get all instances of a service
instances = spring_app.service_discovery.get_instances("my-other-service")
for instance in instances:
print(f"Instance: {instance.base_url}")
Manual Configuration
from spring_ready import SpringReadyApp
spring_app = SpringReadyApp(
app=app,
app_name="my-service",
app_port=8080,
eureka_servers=["http://eureka1:8761/eureka/", "http://eureka2:8761/eureka/"],
profile="production",
fail_fast=True,
prefer_ip_address=True
)
spring_app.start()
Custom IP Address Registration
from spring_ready import SpringReadyApp
# Specify a custom IP address for Eureka registration
# Useful in Docker/Kubernetes when you need to advertise a specific IP
spring_app = SpringReadyApp(
app=app,
app_name="my-service",
instance_ip="192.168.1.100", # Custom IP address
instance_hostname="my-service.example.com" # Optional: custom hostname
)
spring_app.start()
Or via environment variables:
export EUREKA_INSTANCE_IP=192.168.1.100
export EUREKA_INSTANCE_HOSTNAME=my-service.example.com
HTTPS Registration (Secure Mode)
When your application uses HTTPS, you need to register with HTTPS URLs in Eureka so that Spring Boot Admin and other services can connect to it correctly.
from spring_ready import SpringReadyApp
# Register with HTTPS URLs in Eureka
spring_app = SpringReadyApp(
app=app,
app_name="my-service",
app_port=8443,
secure=True # Register with https:// URLs
)
spring_app.start()
Or via environment variable:
export EUREKA_INSTANCE_SECURE=true
When secure=True:
- The
homePageUrl,statusPageUrl, andhealthCheckUrlwill usehttps:// - The
securePortwill be enabled and set to yourapp_port - The regular
portwill be disabled
This is equivalent to Spring Boot's:
eureka:
instance:
secure-port-enabled: true
non-secure-port-enabled: false
How It Works
Startup Sequence
- Eureka Registration: Registers with Eureka (with retry/backoff)
- Config Discovery: Discovers Config Server from Eureka
- Config Loading: Loads configuration into
os.environ - Actuator Setup: Exposes health, info, and metrics endpoints
- Heartbeat: Starts background thread for Eureka heartbeats (every 30s)
Shutdown Sequence
- Stops heartbeat thread
- Deregisters from Eureka
- Clean exit
Behavior Matching Spring Boot
| Feature | Spring Boot | spring-ready-python |
|---|---|---|
| Fail-fast on startup | ✓ | ✓ |
| Exponential backoff retry | ✓ | ✓ |
| Eureka heartbeat (30s) | ✓ | ✓ |
| Config Server discovery | ✓ | ✓ |
| Actuator endpoints | ✓ | ✓ |
| Graceful shutdown | ✓ | ✓ |
Actuator Endpoints
GET /actuator/health
Returns application health status:
{
"status": "UP",
"components": {
"diskSpace": {"status": "UP"},
"eureka": {"status": "UP"},
"ping": {"status": "UP"}
}
}
GET /actuator/info
Returns application metadata:
{
"app": {
"name": "my-python-service",
"version": "1.0.0"
},
"python": {
"version": "3.11.5",
"runtime": {
"name": "CPython",
"version": "3.11.5"
}
}
}
GET /actuator/prometheus
Returns Prometheus metrics in exposition format:
# HELP python_info Python platform information
# TYPE python_info gauge
python_info{implementation="CPython",version="3.11.5"} 1.0
...
Troubleshooting
No Registration Attempts to Eureka Server
Symptom: You don't see any connection attempts to your Eureka server in logs or network monitoring.
Cause: The application is likely using the default Eureka URL (http://localhost:8761/eureka/) instead of your server.
Solution:
-
Set the environment variable (Recommended):
export EUREKA_SERVER_URL=http://10.10.0.1:8761/eureka/ python your_app.py
-
Or pass it explicitly in code:
spring_app = SpringReadyApp( app, eureka_servers=["http://10.10.0.1:8761/eureka/"] )
-
Verify your configuration:
import os print(f"EUREKA_SERVER_URL: {os.getenv('EUREKA_SERVER_URL')}")
-
Check the startup logs: Look for this message:
INFO:spring_ready.core:Configured Eureka server(s): http://10.10.0.1:8761/eureka/If you see:
WARNING:spring_ready.core:Using default Eureka server URL (http://localhost:8761/eureka/)Then you need to set
EUREKA_SERVER_URL. -
Enable debug logging to see detailed registration attempts:
import logging logging.basicConfig(level=logging.DEBUG)
-
Verify network connectivity:
curl http://10.10.0.1:8761/eureka/appsShould return XML/JSON with registered applications.
Common mistakes:
- Forgetting to set
EUREKA_SERVER_URLin Docker/Kubernetes deployments - Setting the variable in your IDE but not in the runtime environment
- Using
localhostwhen running in containers (use service names or IPs instead)
Eureka Registration Fails
Check Eureka server is reachable:
curl http://eureka:8761/eureka/apps
Set fail_fast=False to start anyway:
spring_app = SpringReadyApp(app, fail_fast=False)
Config Server Not Found
Ensure Config Server is registered in Eureka:
curl http://eureka:8761/eureka/apps/CONFIG-SERVER
Or provide direct URL:
export CONFIG_SERVER_URI=http://config-server:8888
Port Already in Use
Change the port:
spring_app = SpringReadyApp(app, app_port=8081)
Or via environment:
export APP_PORT=8081
Differences from Spring Boot
| Aspect | Spring Boot | Python |
|---|---|---|
| Metrics names | jvm.memory.used |
process_virtual_memory_bytes |
| Runtime info | Java/JVM | Python/CPython |
| Config refresh | /actuator/refresh |
Not supported (restart required) |
| Auto-configuration | Annotations | Explicit initialization |
Requirements
- Python 3.9+
- FastAPI
- requests
Optional:
spring-config-client-pythonfor Config Server supportprometheus-clientfor metrics
License
MIT
Contributing
Contributions welcome! This library is intentionally simple and focused. See CONTRIBUTING.md.
Comparison with Spring Boot
// Spring Boot (Kotlin)
@SpringBootApplication
@EnableDiscoveryClient
class MyApplication
// Configuration in application.yml
# Python equivalent
from spring_ready import SpringReadyApp
from fastapi import FastAPI
app = FastAPI()
spring_app = SpringReadyApp(app)
spring_app.start()
# Configuration from environment variables
Note: This library focuses on making Python apps work with existing Spring Boot infrastructure. It's not a replacement for Spring Boot itself.
Release files for spring-ready-python 1.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| spring_ready_python-1.1.2.tar.gz | 53.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| spring_ready_python-1.1.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 109.3 kB
Release files / spring_ready_python-1.1.2.tar.gz
| Download URL | spring_ready_python-1.1.2.tar.gz |
|---|---|
| Size | 53.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
8c1ab4ec19979313c0137a617136acb2d0bba38277b2788ac190475f0cf3c60c
|
|
BLAKE2b-256 checksum How to use checksums |
2adcf270f0705c386b92a243f7b530e03ea16fc0e362a2a3d166dd22b2f16e18
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 11, 2026.
Transparency logRelease files / spring_ready_python-1.1.2-py3-none-any.whl
| Download URL | spring_ready_python-1.1.2-py3-none-any.whl |
|---|---|
| Size | 56.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
76385ea764924dec2d5ef3d089aad3811884c68d3e5eb95e42a42640d9513a1b
|
|
BLAKE2b-256 checksum How to use checksums |
667f25f183e5176acca68ded9bf389dec99bea1f95037dd34016a1153578d414
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Feb 11, 2026.
Transparency log