Skip to content

Home

The speed of a velociraptor, the flexibility of Python.

A micro framework built to hunt.

VelociPy logo

PyPI - Version PyPI - Python Version PyPI - License
PePy - Downloads GitLab Pipeline Status GitLab Coverage GitLab Last Commit GitLab Issues
Libraries.io dependency status Python - Formatter Python - MyPy Git hooks
RSGI ASGI


VelociPy doesn't lumber through the jungle with bulked-up gear. It stays light, feathered, and alert - reading the terrain, then striking with a sickle claw when the moment is right. When the hunt calls for sharper talons, tougher hide, or a keener nose, it grows them - then sheds them when the job is done.

The result is a micro framework with a tiny core and a set of swappable adapters and optional modules. Start with nothing but the core. Add validation, OpenAPI, security, rate limiting, multipart uploads, Redis storage, and more by importing what you need. Only httpx2 is required at runtime.


Why hunt with VelociPy?

  • Light bones, fast muscles - a radix-tree router, lightweight request/response objects, and precomputed handler plans keep the core tiny.
  • Hunt on any terrain - the same app runs unchanged on ASGI (Uvicorn, Hypercorn) or RSGI (Granian).
  • Swap your claws - pick your JSON encoder, model validator, and protocol independently.
  • Keen senses - typed parameters for query, header, cookie, path, and body injection.
  • Armor and discipline - optional security helpers, rate limiting, and request-size limits.

Quick start

Create main.py:

from velocipy import VelociPy

app = VelociPy()

@app.get("/")
async def hello():
    return {"message": "Hello, VelociPy!"}

Run it under the fastest terrain:

# RSGI - the open plain
granian main:app --interface rsgi --reload

# ASGI - the dense, well-trodden forest
uvicorn main:app --reload

Visit http://localhost:8000/docs for the auto-generated Swagger UI.

RSGI is the fastest strike

For raw throughput, run VelociPy under Granian with RSGI. For compatibility with the broader async ecosystem, use ASGI.

A hunt in one file

This single file shows the essentials: validation, dependencies, rate limiting, headers, and OpenAPI tags.

from typing import Annotated
from pydantic import BaseModel
from velocipy import Depends, Header, Query, VelociPy
from velocipy.limiter import (
    Limiter,
    RateLimitAlgorithm,
    RateLimitRule,
    rate_limit,
)
from velocipy.storage import MemoryStorage

app = VelociPy()
limiter = Limiter(storage=MemoryStorage())

class Item(BaseModel):
    name: str
    price: float

async def page_params(
    page: Annotated[int, Query(ge=1)] = 1,
    size: Annotated[int, Query(le=100)] = 20,
):
    return {"page": page, "size": size}

rule = RateLimitRule(
    name="items",
    limit=60,
    window=60,
    algorithm=RateLimitAlgorithm.TOKEN_BUCKET,
)

@app.get("/items", response_model=list[Item], tags=["items"])
async def list_items(
    params: Annotated[dict, Depends(page_params)],
    _: None = Depends(rate_limit(limiter, rules=[rule])),
    x_request_id: Annotated[str | None, Header()] = None,
):
    return [{"name": "hoodie", "price": 49.99}]

Test the catch in-process:

from velocipy.testing import TestClient

client = TestClient(app)
assert client.get("/items?page=1").status_code == 200

See examples/basic.py for a runnable version with lifespan events, custom OpenAPI metadata, and authentication dependencies.

The raptor at a glance

Gear What's included
Routing Radix-tree router, static / parametric / typed / catch-all routes, sub-routers, named routes
Requests & responses Read query, header, cookie, path, and body parameters; shape JSON, streaming, file, and custom responses
Dependencies Sub-dependencies, generator yield teardown, async context managers, overrides
Forms URL-encoded and multipart form field injection
Uploads UploadFile with multipart streaming
Static files StaticFiles with app.mount()
Templating Optional Jinja2 Templates / TemplateResponse
Middleware CORS, GZip, HTTPS redirect, trusted host, security headers, timing, request ID
Background tasks Post-response work
WebSockets Text/bytes/json frames, path params, and subscriptions
Sessions Signed session cookies via SessionMiddleware (stdlib-only signing)
Security API-key header / query / cookie, OAuth2 password bearer, HTTP Basic
Rate limiting Dependency-based token / fixed / sliding window limits with memory + Redis storage
Caching Server-side route response cache with shared memory + Redis storage
OpenAPI Auto-generated 3.1 docs with reusable schemas, route metadata, and Swagger UI
API versioning Path, header, Accept, and deprecation versioning
GraphQL Strawberry schema over HTTP and WebSocket with subscriptions and file uploads
Config Immutable typed Config container with @Config.register / Config.get
Testing Built-in TestClient and AsyncTestClient for ASGI and RSGI

Choose your terrain

Terrain Best for
RSGI (Granian) Maximum speed, lowest overhead. The open plain.
ASGI (Uvicorn / Hypercorn) Compatibility with the broad async ecosystem. The dense forest.

Example hunts

The examples/ directory has small, runnable demos. Start with the essentials, then move through common patterns and advanced integrations.

Start here

Example What it shows
basic.py Validation, OpenAPI, dependencies, lifespan
routing.py Routes, path params, sub-routers, catch-all routes
query_params.py Query parameter parsing and validation
dependencies.py Dependency injection patterns
responses.py Custom and streaming responses

Common patterns

Example What it shows
security.py API-key and OAuth2 authentication
rate_limit.py Dependency-based rate limiting
caching.py Server-side route response caching
middleware.py Function, class, and built-in middleware
testing.py Testing with TestClient and AsyncTestClient
uploads.py UploadFile and multipart streaming
background_tasks.py Post-response background work
sessions.py Signed session cookies
form_parameters.py Form(...) field injection
websocket.py WebSocket echo and path params
headers_cookies.py Header and cookie injection
query_method.py HTTP QUERY method with body-aware caching

Advanced and integrations

Example What it shows
api_versioning.py Path, header, Accept, and deprecation versioning
config.py Typed Config classes
exception_handlers.py Custom exception handlers
graphql.py GraphQL queries, mutations, subscriptions, and file uploads
json_encoder.py Explicit JSON encoder selection
max_body_size.py Global max_content_length
model_backends.py msgspec / pydantic / custom model backends
route_extras.py Route decorator metadata
static_files.py Static file serving
templates.py Optional Jinja2 templating
uvicorn_server.py Running a VelociPy app with Uvicorn via ASGI

Next steps

  • Getting started - install VelociPy and build your first app.
  • Routing - routes, parameters, and handlers.
  • Requests & responses - read the request and shape the response.
  • Dependencies - share logic with dependency injection.
  • Uploads - multipart file uploads with UploadFile.
  • Testing - test apps in-process with TestClient and AsyncTestClient.
  • API Versioning - version by path, header, or Accept header.
  • GraphQL - expose a Strawberry schema over HTTP and WebSocket.
  • Deployment - run in production on RSGI or ASGI.