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.

[!TIP] Check out the full documentation and our examples to get started.

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 ILoggerUserModule 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.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

waku-0.43.0.tar.gz (65.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

waku-0.43.0-py3-none-any.whl (116.0 kB view details)

Uploaded Python 3

File details

Details for the file waku-0.43.0.tar.gz.

File metadata

  • Download URL: waku-0.43.0.tar.gz
  • Upload date:
  • Size: 65.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for waku-0.43.0.tar.gz
Algorithm Hash digest
SHA256 eefc015daa6dbf36d160b97c54b29ccc9b56fbfc0bc00efc5d315d3e0cd6269a
MD5 d2feda0bb28537c8ed8e4d0666e1ffea
BLAKE2b-256 c658055cd6d3089c27985d09b461f0b095e51b476261a98b11279ff9d045f1e7

See more details on using hashes here.

Provenance

The following attestation bundles were made for waku-0.43.0.tar.gz:

Publisher: release.yml on waku-py/waku

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file waku-0.43.0-py3-none-any.whl.

File metadata

  • Download URL: waku-0.43.0-py3-none-any.whl
  • Upload date:
  • Size: 116.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for waku-0.43.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8890fcb6f93dfc3c09a6f06388a66d72d5e22adc72d9b098c819c6a3b41096d5
MD5 e006c3030c58844dd42dfdac2921cf56
BLAKE2b-256 47e8869837b65ef2ac73bccbd2676f40fd3be417bde5bb84e7603db0b1303590

See more details on using hashes here.

Provenance

The following attestation bundles were made for waku-0.43.0-py3-none-any.whl:

Publisher: release.yml on waku-py/waku

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.43.0 This release

2 files

0.42.0

2 files

0.41.2

2 files

0.41.1

2 files

0.41.0

2 files

0.40.0

2 files

0.39.0

2 files

0.38.0

2 files

0.37.0

2 files

0.36.0

2 files

0.35.1

2 files

0.35.0

2 files

0.34.1

2 files

0.34.0

2 files

0.33.0

2 files

0.32.0

2 files

0.31.0

2 files

0.30.0

2 files

0.29.0

2 files

0.28.1

2 files

0.28.0

2 files

0.27.0

2 files

0.26.1

2 files

0.26.0

2 files

0.25.0

2 files

0.24.1

2 files

0.24.0

2 files

0.23.0

2 files

0.22.2

2 files

0.22.1

2 files

0.22.0

2 files

0.21.0

2 files

0.20.0

2 files

0.19.0

2 files

0.18.0

2 files

0.17.0

2 files

0.16.0

2 files

0.15.0

2 files

0.14.0

2 files

0.13.0

2 files

0.12.1

2 files

0.12.0

2 files

0.11.3

2 files

0.11.2

2 files

0.11.1

2 files

0.11.0

2 files

0.10.0

2 files

0.9.1

2 files

0.9.0

2 files

0.8.0

2 files

0.7.0

2 files

0.6.0

2 files

0.5.0

2 files

0.4.0

2 files

0.3.1

2 files

0.3.0

2 files

0.2.0

2 files

0.1.6

2 files

0.1.5

2 files

0.1.4

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page