Skip to main content

waku logo

waku [枠 or わく] means framework in Japanese.


CI/CD codecov GitHub issues GitHub contributors GitHub commit activity GitHub license

PyPI Python version Downloads

uv Ruff ty pyrefly mypy - checked

Telegram Ask DeepWiki


Python makes it easy to build a backend. waku makes it easy to keep growing one.

As your project scales, problems creep in: services import each other freely, swapping a database means editing dozens of files, and nobody can tell which module depends on what. waku gives you modules with explicit boundaries, type-safe DI powered by dishka, and integrated CQRS and event sourcing — so your codebase stays manageable as it scales.

The Problem

Python has no built-in way to enforce component boundaries. Packages don't control visibility, imports aren't validated, and nothing stops module A from reaching into the internals of module B. As a project grows, what started as clean separation quietly becomes a web of implicit dependencies — where testing requires the whole system, onboarding means reading everything, and changing one module risks breaking three others.

What waku gives you

Structure

  • 🧩 Package by component: Each module is a self-contained unit with its own providers. Explicit imports and exports control what crosses boundaries — validated at startup, not discovered in production.
  • 💉 Dependency inversion: Define interfaces in your application core, bind adapters in infrastructure modules. Swap a database, a cache, or an API client by changing one provider — powered by dishka.
  • 🔌 One core, any entrypoint: Build your module tree once with WakuFactory. Plug it into FastAPI, Litestar, FastStream, Aiogram, CLI, or workers — same logic everywhere.

Capabilities

  • 📨 Messaging: DI alone doesn't decouple components — you need events. The message bus dispatches commands, queries, and events so components never reference each other directly. Pipeline behaviors handle cross-cutting concerns.
  • 📜 Event sourcing: Aggregates, projections, snapshots, upcasting, and the decider pattern with built-in SQLAlchemy adapters.
  • 🧪 Testing: Override any provider in tests with override(), or spin up a minimal app with create_test_app().
  • 🧰 Lifecycle & extensions: Hook into startup, shutdown, and module initialization. Add validation, logging, or custom behaviors — decoupled from your business logic.

Quick Start

Installation

uv add waku

Minimal Example

Define a service, register it in a module, and resolve it from the container:

import asyncio

from waku import WakuFactory, module
from waku.di import scoped


class GreetingService:
    async def greet(self, name: str) -> str:
        return f'Hello, {name}!'


@module(providers=[scoped(GreetingService)])
class GreetingModule:
    pass


@module(imports=[GreetingModule])
class AppModule:
    pass


async def main() -> None:
    app = WakuFactory(AppModule).create()

    async with app, app.container() as c:
        svc = await c.get(GreetingService)
        print(await svc.greet('waku'))


if __name__ == '__main__':
    asyncio.run(main())

Module Boundaries in Action

Modules control visibility. InfrastructureModule exports ILogger — UserModule imports it. Dependencies are explicit, not implicit:

import asyncio
from typing import Protocol

from waku import WakuFactory, module
from waku.di import scoped, singleton


class ILogger(Protocol):
    async def log(self, message: str) -> None: ...


class ConsoleLogger(ILogger):
    async def log(self, message: str) -> None:
        print(f'[LOG] {message}')


class UserService:
    def __init__(self, logger: ILogger) -> None:
        self.logger = logger

    async def create_user(self, username: str) -> str:
        user_id = f'user_{username}'
        await self.logger.log(f'Created user: {username}')
        return user_id


@module(
    providers=[singleton(ILogger, ConsoleLogger)],
    exports=[ILogger],
)
class InfrastructureModule:
    pass


@module(
    imports=[InfrastructureModule],
    providers=[scoped(UserService)],
)
class UserModule:
    pass


@module(imports=[UserModule])
class AppModule:
    pass


async def main() -> None:
    app = WakuFactory(AppModule).create()

    async with app, app.container() as c:
        user_service = await c.get(UserService)
        user_id = await user_service.create_user('alice')
        print(f'Created user with ID: {user_id}')


if __name__ == '__main__':
    asyncio.run(main())

Next steps

Documentation

Contributing

Top contributors

contrib.rocks image

Roadmap

  • Create logo
  • Improve inner architecture
  • Improve documentation
  • Add new and improve existing validation rules
  • Provide example projects for common architectures

Support

License

This project is licensed under the terms of the MIT License.

Acknowledgements

  • dishka – Dependency Injection framework powering waku IoC container.
  • NestJS – Inspiration for modular architecture and design patterns.
  • Wolverine (C#) – Inspiration for messaging, transport model, and pipeline architecture.
  • Marten (C#) – Inspiration for event sourcing, projections, and document store design.
  • Emmett – Functional-first event sourcing patterns.
  • Eventuous – Event store interface design.
  • Jérémie Chassaing – Decider pattern formalization.

Metadata

Release files for waku 0.43.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for waku 0.43.0
File Size Uploaded
waku-0.43.0.tar.gz 65.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for waku 0.43.0
File Interpreter ABI Platform
waku-0.43.0-py3-none-any.whl Python 3 none any Details

Total release size: 181.6 kB

Release files / waku-0.43.0.tar.gz

Download URL waku-0.43.0.tar.gz
Size 65.6 kB
Tags Source
SHA-256 checksum
How to use checksums
eefc015daa6dbf36d160b97c54b29ccc9b56fbfc0bc00efc5d315d3e0cd6269a
BLAKE2b-256 checksum
How to use checksums
c658055cd6d3089c27985d09b461f0b095e51b476261a98b11279ff9d045f1e7
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 Mar 28, 2026.

Transparency log

Release files / waku-0.43.0-py3-none-any.whl

Download URL waku-0.43.0-py3-none-any.whl
Size 116.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8890fcb6f93dfc3c09a6f06388a66d72d5e22adc72d9b098c819c6a3b41096d5
BLAKE2b-256 checksum
How to use checksums
47e8869837b65ef2ac73bccbd2676f40fd3be417bde5bb84e7603db0b1303590
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 Mar 28, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.43.0 This release

2 release files

0.42.0

2 release files

0.41.2

2 release files

0.41.1

2 release files

0.41.0

2 release files

0.40.0

2 release files

0.39.0

2 release files

0.38.0

2 release files

0.37.0

2 release files

0.31.0

2 release files

0.30.0

2 release files

0.29.0

2 release files

0.28.1

2 release files

0.28.0

2 release files

0.27.0

2 release files

0.23.0

2 release files

0.22.2

2 release files

0.22.1

2 release files

0.22.0

2 release files

0.21.0

2 release files

0.20.0

2 release files

0.18.0

2 release files

0.17.0

2 release files

0.14.0

2 release files

0.13.0

2 release files

0.12.1

2 release files

0.12.0

2 release files

0.11.3

2 release files

0.11.2

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.1

2 release files

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.6

2 release files

0.1.5

2 release files

0.1.4

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page