Convention over Configuration
+Production-ready defaults for every module. A complete web service is a few lines of YAML — override only what matters.
+Spring Boot's cohesion, native to async Python.
++ Build production-grade microservices with the patterns you trust — dependency injection, + CQRS, event-driven architecture, sagas, event sourcing — all integrated, all consistent, + with production-ready defaults from the first commit. +
+ + + +$ curl -fsSL https://raw.githubusercontent.com/fireflyframework/fireflyframework-pyfly/main/install.sh | bash
+
+ Why PyFly
++ Every new service starts with two weeks of decisions — web framework, ORM, message broker, + DI wiring, project layout. Six months later a second team makes entirely different choices. + Now you have two codebases with nothing in common. PyFly makes these decisions for you — + one cohesive, full-stack programming model where every module is designed to work together. +
+DI, HTTP, data, messaging, caching, security, observability — integrated, consistent, and wired automatically. No bespoke glue.
+The same enterprise model Firefly proved on Spring Boot (40+ Java modules), reimagined for async/await, type hints, and Protocols.
Stereotypes, auto-configuration, Spring-Data repositories, actuator. A Spring-parity callout at every turn.
+No boilerplate. No manual wiring.
+The DI container resolves dependencies from type hints, validates request bodies, and publishes domain events — all out of the box. Same model, whether you're building a controller, a CQRS bus, or a distributed saga.
+ +from pyfly.container import rest_controller, service
+from pyfly.web import request_mapping, post_mapping, Body, Valid
+
+@service
+class OrderService:
+ def __init__(self, repo: OrderRepository, events: EventPublisher) -> None:
+ self._repo = repo
+ self._events = events
+
+ async def place_order(self, order: Order) -> Order:
+ saved = await self._repo.save(order)
+ await self._events.publish(OrderPlaced(order_id=saved.id))
+ return saved
+
+@rest_controller
+@request_mapping("/orders")
+class OrderController:
+ def __init__(self, service: OrderService) -> None:
+ self._service = service
+
+ @post_mapping("", status_code=201)
+ async def create(self, order: Valid[Body[Order]]) -> Order:
+ return await self._service.place_order(order)from pyfly.cqrs import command, query, CommandHandler, QueryHandler
+
+@command(CreateUser)
+class CreateUserHandler(CommandHandler[CreateUser, int]):
+ def __init__(self, repo: UserRepository) -> None:
+ self._repo = repo
+
+ async def handle(self, cmd: CreateUser) -> int:
+ return (await self._repo.save(User(name=cmd.name, email=cmd.email))).id
+
+@query(FindUserById, cache_ttl=60) # caching composes declaratively
+class FindUserByIdHandler(QueryHandler[FindUserById, User]):
+ def __init__(self, repo: UserRepository) -> None:
+ self._repo = repo
+
+ async def handle(self, q: FindUserById) -> User:
+ return await self._repo.find_by_id(q.user_id)
+
+# Dispatch — buses are auto-wired by the CqrsAutoConfiguration entry point
+user_id = await commands.dispatch(CreateUser(name="Ada", email="ada@example.com"))
+user = await queries.dispatch(FindUserById(user_id=user_id))from pyfly.transactional.saga import saga, saga_step
+from pyfly.transactional.saga.core.context import SagaContext
+
+@saga(name="place-order", timeout_ms=30_000)
+class PlaceOrderSaga:
+ # `compensate=` names a method to invoke if a later step fails.
+ @saga_step(id="reserve-inventory", retry=3, backoff_ms=500, compensate="release_inventory")
+ async def reserve(self, ctx: SagaContext) -> str:
+ return await self._inventory.reserve(ctx.input["order_id"])
+
+ async def release_inventory(self, ctx: SagaContext) -> None:
+ await self._inventory.release(ctx.input["order_id"])
+
+ @saga_step(id="charge-payment", depends_on=["reserve-inventory"], compensate="refund_payment")
+ async def charge(self, ctx: SagaContext) -> str:
+ return await self._payments.charge(ctx.input["order_id"], ctx.input["amount"])
+
+ @saga_step(id="ship-order", depends_on=["charge-payment"])
+ async def ship_order(self, ctx: SagaContext) -> None:
+ await self._ship.dispatch(ctx.input["order_id"])Philosophy
+Production-ready defaults for every module. A complete web service is a few lines of YAML — override only what matters.
+Business logic never imports sqlalchemy, redis, or aiokafka. Hexagonal ports & adapters keep infrastructure swappable.
Built for asyncio from the ground up. Every public surface is fully typed and checked by mypy in strict mode.
Structured logging, correlation IDs, PII redaction, health checks, Prometheus metrics, OWASP headers, graceful shutdown — the baseline.
+Architecture
+Five layers on an async core. Every external system reached through a Protocol port. The right adapters wired automatically at startup — so you can swap PostgreSQL for MongoDB, or Kafka for RabbitMQ, without touching a line of business logic.
+Featured Patterns
+PyFly ships production-grade implementations of the distributed patterns that power real microservices — each a first-class module with port-and-adapter design, CLI scaffolding, metrics, tracing, and persistence.
+Distributed transactions with automatic compensation. Parallel DAG execution, per-step retries, idempotency keys, DLQ + recovery.
+ transactional → +Durable, signal-driven orchestration. Wait for signals or timers, spawn child workflows, query while running. Temporal-style, native.
+ transactional → +Try / Confirm / Cancel — strong-consistency three-phase transactions for financial workloads where compensation alone isn't enough.
+ transactional → +Append-only event log, aggregates that rebuild from history, snapshots, transactional outbox, projections, upcasting.
+ eventsourcing → +Command/Query buses with validation, authorization, and caching composing declaratively as cross-cutting concerns.
+ cqrs → +Externalize business rules in a YAML DSL with AST evaluation, audit trails, batch evaluation, and hot reload.
+ rule-engine → +Modules
+Everything from HTTP routing and database access to distributed transactions, identity, content management, and DDD building blocks.
+Quickstart
+curl -fsSL https://raw.githubusercontent.com/fireflyframework/fireflyframework-pyfly/main/install.sh | bashpyfly new my-service --archetype web-api && cd my-servicepyfly run --reloadcurl http://localhost:8080/health # {"status":"UP"}OpenAPI / Swagger UI at http://localhost:8080/docs
The Book
+The official, project-driven book. Across 18 chapters in five parts it builds Lumen — a real wallet & ledger microservice — from an empty folder into a secured, observable, event-driven service. Every listing is drawn from a running project. Spring developers get a parity callout at every turn.
+ +The Firefly Ecosystem
+PyFly is the green firefly of the Firefly Framework family — the same cohesive model on Java/Spring Boot, .NET, Rust, Go, and Angular.
+