Build Microservices
at Lightning Speed
A fast, lightweight, single-file Python WSGI framework. Zero dependencies. Production-grade. One file. async def supported.
Python 3.8+ | v0.0.4 | Early Release | MIT | Zero Dependencies
Quick Install
pip install lcore
Zero dependencies only Python 3.8+ required. Every import is from the standard library.
Hello World
from lcore import Lcore
app = Lcore()
@app.route('/hello')
def hello():
return {'message': 'Hello, World!'}
app.run(host='0.0.0.0', port=8080)
Performance
WSGI throughput benchmark 100,000 iterations × 3 runs per framework, best run recorded. Measures pure framework overhead.
| Test | Lcore | Flask 3.1.3 | Bottle 0.13.4 | Lcore vs Flask |
|---|---|---|---|---|
| Plaintext | 116,794 | 25,497 | 187,334 | 4.6x |
| JSON | 91,917 | 22,757 | 138,299 | 4.0x |
| Route Params | 85,260 | 21,267 | 125,331 | 4.0x |
| Middleware (2 layers) | 45,791 | 20,673 | 114,821 | 2.2x |
| 404 Miss | 33,841 | 13,480 | 38,696 | 2.5x |
| Multi-Route (50 routes) | 93,183 | 22,692 | 142,385 | 4.1x |
| POST JSON | 58,447 | 17,808 | 95,209 | 3.3x |
Lcore is 2.2x – 4.6x faster than Flask across all 7 test scenarios. Bottle is faster on raw throughput but lacks middleware, DI, security stack, and lifecycle hooks that Lcore provides out of the box. See the full feature comparison.
Feature Comparison
How Lcore compares to other Python microframeworks.
| Feature | Lcore | Flask | Bottle | FastAPI |
|---|---|---|---|---|
| Single file / zero deps | Yes | No | Yes | No |
| WSGI | Yes | Yes | Yes | No |
| ASGI | No | No | No | Yes |
| Async route handlers | Yes ⚠ | Yes (2.0+) | No | Yes |
| Typed route parameters | Yes | Yes | Yes | Yes |
| Custom route filters | Yes | Yes | Yes | No |
| Route groups | Yes | Blueprints | No | APIRouter |
| Built-in middleware | 7 included | 0 | 0 | Several |
| CORS middleware | Built-in | Extension | Plugin | Built-in |
| CSRF protection | Built-in | Extension | No | No |
| Security headers | Built-in | Extension | No | No |
| Rate limiting | Built-in (per-process; pass backend= for shared) | Extension | No | Extension |
| Request validation | Built-in | Extension | No | Built-in |
| Dependency injection | Built-in (3 lifetimes) | No | No | Built-in |
| Plugin system | Yes | Extensions | Yes | No |
| Lifecycle hooks | 12 hook points | Signals | 6 hooks | Events |
| Module mounting | Yes (WSGI) | Blueprints | Yes | Sub-apps |
| Template engines | 4 engines | Jinja2 | SimpleTemplate | Jinja2 |
| Signed cookies | HMAC-SHA256 | itsdangerous | HMAC | No |
| Static file serving | Yes (ETag, Range) | Yes | Yes | Yes |
| Server adapters | 21 adapters | Werkzeug | 20+ adapters | Uvicorn |
| Hot reload | Built-in + Watchdog | Werkzeug | Yes | Uvicorn |
| CLI interface | Yes | Yes | No | No |
| Auto API docs (HTML + JSON) | Built-in | No | No | OpenAPI/Swagger |
| Body size limits | Built-in | Config | Config | Config |
| Gzip compression | Built-in | Extension | No | Middleware |
| Request ID tracking | Built-in | Extension | No | Extension |
| Password hashing | PBKDF2-SHA256 | Extension | No | No |
| Test client | Built-in | Built-in | No | Built-in |
| Background tasks | Built-in | Celery | No | Built-in |
| Graceful shutdown | Built-in | Server | No | Server |
Why Lcore Exists
Most Python frameworks make one of two trade-offs: simple and fast (Bottle) but with no middleware, no DI, and no security stack or full-featured (Flask, Django) but dependent on many extensions and slower under load. Lcore closes that gap.
| Framework | What it does |
|---|---|
| Bottle | Single file, zero deps, fast. But no middleware stack, no dependency injection, no security primitives, no lifecycle hooks. You build all of that yourself. |
| Flask | Popular and well-documented. But you need flask-cors, flask-limiter, flask-login, and many more before you have a production API and each is a dependency. |
| Lcore | Single file, zero deps, 3 to 4x faster than Flask, with CORS, CSRF, security headers, rate limiting, PBKDF2 hashing, DI, 12 lifecycle hooks, and a test client all built in. Nothing to install beyond Lcore itself. |
Design Philosophy
lcore.py. No package structure, no sub-modules, no build step. Drop it into any project and import it.
pip may not be available.
unittest from the standard library. Run it anywhere with python -m pytest tests/ after installing pytest.
When NOT to use Lcore
Lcore is a strong fit for synchronous WSGI workloads. It is the wrong choice in these situations:
| Situation | Better choice |
|---|---|
| You need WebSockets or real-time async I/O | FastAPI, Starlette, Quart |
| You need true async concurrency (async DB drivers, hundreds of simultaneous outbound calls) | FastAPI, Starlette |
| Your team is already on Flask and migration cost outweighs any benefit | Stay on Flask |
| You need automatic OpenAPI / Swagger generation | FastAPI |
| You need ASGI and Uvicorn / Daphne today | FastAPI, Starlette |
| Your workload is I/O-bound and you want event-loop concurrency | FastAPI, Starlette |
| You need a full MVC framework with ORM, admin panel, and migrations | Django |
Your workload is primarily synchronous: REST APIs, internal services, background job APIs, or microservices that talk to SQL databases via sync drivers (psycopg2, sqlite3, mysqlclient). If you want maximum feature density in a single file with no installation ceremony, Lcore is built for that.
Ideal Use Cases
psycopg2, sqlite3, or mysqlclient.
pip access required. Works anywhere Python 3.8+ runs.
Key Features
async def handlers accepted with automatic wrapping see the async caveat.
Lcore accepts
async def route handlers, but the worker thread is blocked for the full duration. No concurrency benefit. Full details.
server='auto' to pick the best available.
Used in Production
Lcore is already powering production workloads. The list is small today but every deployment feeds directly into real-world performance analysis and targeted improvements.
Production Microservice
from lcore import (
Lcore, request, response, ctx,
CORSMiddleware, SecurityHeadersMiddleware,
RequestIDMiddleware, BodyLimitMiddleware,
rate_limit, validate_request, on_shutdown
)
app = Lcore()
# Production middleware stack
app.use(RequestIDMiddleware())
app.use(SecurityHeadersMiddleware(hsts=True))
app.use(CORSMiddleware(allow_origins=['https://myapp.com']))
app.use(BodyLimitMiddleware(max_size=5 * 1024 * 1024))
# Dependency injection
app.inject('db', create_db_session, lifetime='scoped')
app.inject('cache', RedisCache, lifetime='singleton')
# Rate-limited, validated API endpoint
@app.route('/api/users/<id:int>', method='GET')
@rate_limit(100, per=60)
def get_user(id):
user = ctx.db.query(User).get(id)
if not user:
abort(404, 'User not found')
return user.to_dict()
@app.post('/api/users')
@validate_request(body={'name': str, 'email': str})
def create_user():
data = request.json
return {'id': ctx.db.insert(data), 'created': True}
# Graceful shutdown
@on_shutdown
def cleanup():
close_all_connections()
app.run(server='gunicorn', host='0.0.0.0', port=8080)
Lcore