Skip to content

Commit 38ad18a

Browse files
authored
docs(planning): refresh the launch playbook against current reality (#47)
The copy was drafted in June and the projects have moved. Verified every claim against PyPI, the GitHub API and each repo's README on 2026-07-13. Corrections: - httpware wraps httpx2 (2.5.0), not httpx, and now ships sync as well as async clients. The copy said "wraps httpx", which is simply false and is exactly what a Show HN thread would catch. - modern-di has 13 official integrations, not the 4 the copy listed (adds Starlette, Flask, aiohttp, Celery, arq, taskiq, aiogram, gRPC). - The Dishka comparison conceded "many more integrations". Dishka has ~15 to modern-di's 13, so that undersold the project. Reframed to what is still true and checkable: Dishka is considerably more established (~1.2k stars), supports async resolution and custom scopes, and integration coverage is now roughly comparable. - 100+ releases -> 116. lite-bootstrap adds FastMCP and Pyroscope. - faststream-outbox is no longer "~weeks old" (first commit 2026-05-07, now 0.10.5 across 29 releases); httpware is still 0.x, so keep the pin advice. Adds a dated facts-checked banner, since these threads are one-shot and the numbers go stale again.
1 parent 5fc32e7 commit 38ad18a

1 file changed

Lines changed: 37 additions & 23 deletions

File tree

planning/launch-playbook.md

Lines changed: 37 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,13 @@
33
Internal asset — **not published** (lives at the repo root, outside the MkDocs `docs/` tree).
44
Ready-to-post copy for the coordinated launch, plus timing and etiquette.
55

6+
> **Facts checked 2026-07-13.** Every number and claim below was verified against
7+
> PyPI, the GitHub API, and each repo's README on that date. Re-check before
8+
> posting — HN and r/Python punish stale specifics, and these threads are
9+
> one-shot. Current: `modern-di` 2.28.0 / 116 releases / 58★ / zero runtime deps /
10+
> 13 integrations; `that-depends` 4.0.2 / 251★; `httpware` 0.15.1 (wraps
11+
> **httpx2**, not httpx); `faststream-outbox` 0.10.5; `lite-bootstrap` 1.2.3.
12+
613
**Design principles**
714
- **Single-focus posts** on link aggregators (HN/Reddit/Lobsters) outperform one
815
sprawling "look at my org" post. Stagger one project per week.
@@ -31,13 +38,13 @@ Suggested order: **modern-di (HN+Reddit)** → **stack announcement** →
3138
> - **Type-based autowiring** — your constructor type hints *are* the graph; no `Provide[...]` markers or string keys.
3239
> - **Explicit scopes** (APP → REQUEST → …) with **build-time** cycle- and scope-violation checks.
3340
> - **Sync resolution by design** — async setup/teardown lives in the framework lifespan, not in resolution. This is deliberate and permanent, not a missing feature.
34-
> - **Official integrations** for FastAPI, Litestar, FastStream, and Typer, plus a first-party pytest plugin that turns any dependency into a fixture.
35-
> - Zero-dependency core, MIT, 100+ releases.
41+
> - **Official integrations** for FastAPI, Litestar, Starlette, Flask, aiohttp, FastStream, Celery, arq, taskiq, aiogram, gRPC, and Typer plus a first-party pytest plugin that turns any dependency into a fixture.
42+
> - Zero-dependency core, MIT, 116 releases.
3643
>
3744
> Where it honestly stands:
3845
> - If you're building a single FastAPI service and everything is request-scoped, FastAPI's `Depends` is enough — you don't need this.
39-
> - The closest library is **Dishka**, which is more established, has many more integrations, and supports async resolution + custom scopes. If you need those, use Dishka. modern-di's bets are a simpler sync-only model, the first-party pytest plugin, and being one consistent small stack.
40-
> - It's young but actively developed.
46+
> - The closest library is **Dishka**, which is considerably more established (~1.2k stars to my ~60) and supports async resolution and custom scopes. If you need either, use Dishka. Integration coverage is now roughly comparable between the two. modern-di's bets are a simpler sync-only model, the first-party pytest plugin, and being one consistent small stack.
47+
> - It's young but actively developed, and deliberately conservative — the docs have a "design decisions" page for what it leaves out on purpose (auto-binding, in-package integrations, graph rendering).
4148
>
4249
> Docs include a full comparison and a "do you even need a DI container?" page: https://modern-di.modern-python.org
4350
> Repo: https://github.com/modern-python/modern-di
@@ -51,20 +58,20 @@ comment; the honest "when not to use it" is what earns goodwill.
5158

5259
## 2. r/Python (Showcase format — three required sections)
5360

54-
**Title:** `modern-di – typed dependency injection with scopes and one wiring across FastAPI, Litestar, FastStream, and Typer`
61+
**Title:** `modern-di – typed dependency injection with scopes and one wiring across FastAPI, Litestar, FastStream, Celery, and Typer`
5562

5663
**Body:**
5764

5865
> **What My Project Does**
59-
> modern-di is a dependency-injection framework. You declare providers once (type-based autowiring from constructor hints), and resolve them with explicit scopes (APP → REQUEST → …) and build-time cycle/scope checks. The same container wires your FastAPI app, your FastStream workers, your Typer CLI, and your tests — via official integrations and a first-party pytest plugin that turns any dependency into a fixture. Sync resolution by design; async lives in the framework lifespan.
66+
> modern-di is a dependency-injection framework. You declare providers once (type-based autowiring from constructor hints), and resolve them with explicit scopes (APP → REQUEST → …) and build-time cycle/scope checks. The same container wires your FastAPI app, your FastStream workers, your Celery/arq/taskiq tasks, your Typer CLI, and your tests — via 13 official integrations and a first-party pytest plugin that turns any dependency into a fixture. Sync resolution by design; async lives in the framework lifespan.
6067
>
6168
> **Target Audience**
6269
> Python teams whose business logic runs behind *more than one entrypoint* (an API plus workers/CLIs) and who want one wiring instead of three. It's production-intended but young — early adopters welcome. If you have a single web service where everything is request-scoped, framework-native `Depends`/`Provide` is enough and modern-di is overkill.
6370
>
6471
> **Comparison**
6572
> - **vs FastAPI `Depends` / Litestar `Provide`:** great inside one app, but don't span workers/CLIs or give typed app-scoped singletons; modern-di shares one wiring across all entrypoints.
6673
> - **vs `dependency-injector`:** type-based autowiring instead of `Provide[...]` markers; nested request scopes; first-party pytest plugin.
67-
> - **vs Dishka** (the closest library): Dishka is more established, has more integrations, and supports async resolution + custom scopes — pick it if you need those. modern-di bets on a simpler sync-only model and a first-party pytest plugin.
74+
> - **vs Dishka** (the closest library): Dishka is considerably more established (~1.2k stars) and supports async resolution + custom scopes — pick it if you need those. Integration coverage is now roughly comparable. modern-di bets on a simpler sync-only model and a first-party pytest plugin.
6875
> - **vs `that-depends`** (my earlier framework): modern-di adds explicit scopes and drops global state; that-depends stays maintained for async resolution.
6976
>
7077
> Docs + comparison: https://modern-di.modern-python.org
@@ -118,10 +125,13 @@ instead of spending the first day assembling boilerplate.
118125
The thing that tends to rot first in a growing service is dependency wiring.
119126
modern-di is a typed DI container built around one idea: *one wiring shared across
120127
every entrypoint.* The same container resolves dependencies in your FastAPI
121-
handlers, your FastStream workers, and your Typer CLI — instead of three parallel
122-
copies that drift apart. It uses type-based autowiring (your constructor hints are
123-
the graph), explicit scopes with build-time validation, and a first-party pytest
124-
plugin that turns any dependency into a fixture. It's deliberately sync-only:
128+
handlers, your FastStream workers, your Celery tasks, and your Typer CLI — instead
129+
of four parallel copies that drift apart. Thirteen official integrations cover the
130+
web frameworks (FastAPI, Litestar, Starlette, Flask, aiohttp), the task queues
131+
(Celery, arq, taskiq), messaging, gRPC, and the CLI. It uses type-based autowiring
132+
(your constructor hints are the graph), explicit scopes with build-time validation,
133+
and a first-party pytest plugin that turns any dependency into a fixture. It's
134+
deliberately sync-only:
125135
async setup and teardown belong in the framework lifespan, not in resolution. If
126136
you only have a single web service, your framework's own `Depends` is enough —
127137
modern-di earns its place when you have a second entrypoint. (The docs include an
@@ -130,10 +140,11 @@ DI?" page.)
130140

131141
**Call other services with [`httpware`](https://httpware.modern-python.org).**
132142
As soon as a service talks to other services, you need more than a bare HTTP
133-
client. httpware wraps httpx with the things you'd otherwise assemble yourself:
134-
typed errors (4xx/5xx become a status-keyed exception tree, no more
135-
`raise_for_status`), typed response bodies (decode straight to your pydantic or
136-
msgspec model), and resilience as composable middleware — retry with budget,
143+
client. httpware is an HTTP client framework, with sync and async clients, built
144+
on [httpx2](https://pypi.org/project/httpx2/). It supplies what you'd otherwise
145+
assemble yourself: typed errors (4xx/5xx become a status-keyed exception tree, no
146+
more `raise_for_status`), typed response bodies (decode straight to your pydantic
147+
or msgspec model), and resilience as composable middleware — retry with budget,
137148
bulkhead, and circuit breaker, ordered explicitly.
138149

139150
**Publish events reliably with
@@ -148,8 +159,9 @@ decorator. At-least-once delivery, with a dead-letter option.
148159
**Instrument everything with
149160
[`lite-bootstrap`](https://lite-bootstrap.modern-python.org).**
150161
Finally, observability. lite-bootstrap wires OpenTelemetry, Prometheus, Sentry,
151-
and structlog into a FastAPI, Litestar, or FastStream service in a few lines —
152-
each instrument opt-in, each skipped automatically if you don't configure it.
162+
Pyroscope, and structlog into a FastAPI, Litestar, FastStream, or FastMCP service
163+
in a few lines — each instrument opt-in, each skipped automatically if you don't
164+
configure it.
153165
Consistent instrumentation across a fleet of services, without copy-pasting 150
154166
lines of setup into every repo.
155167

@@ -167,10 +179,12 @@ missing.
167179

168180
- **Show HN: faststream-outbox** — "the transactional outbox pattern for
169181
FastStream + Postgres." Outbox is a respected, technical topic. Honest framing:
170-
the pattern is battle-tested, the library is ~weeks old.
171-
- **Show HN / r/Python: httpware** — "httpx clients with typed errors + composable
172-
resilience (retry/bulkhead/circuit-breaker)." Resilience patterns draw
173-
discussion. Beta; pin versions.
182+
the pattern is battle-tested, the library is young (first commit 2026-05-07,
183+
now 0.10.5 across 29 releases).
184+
- **Show HN / r/Python: httpware** — "a Python HTTP client framework: sync + async
185+
clients on httpx2, with typed errors and composable resilience
186+
(retry/bulkhead/circuit-breaker)." Resilience patterns draw discussion. Still
187+
0.x — say so, and tell people to pin.
174188

175189
(Reuse the modern-di structures above: HN = honest "what/where-it-stands";
176190
r/Python = What-it-does / Target-audience / Comparison.)
@@ -183,9 +197,9 @@ r/Python = What-it-does / Target-audience / Comparison.)
183197

184198
## 7. Social one-liners (X / Mastodon / Bluesky)
185199

186-
- "One typed DI wiring for your FastAPI app, FastStream workers, and Typer CLI — not three. modern-di, sync-by-design: https://modern-di.modern-python.org"
200+
- "One typed DI wiring for your FastAPI app, FastStream workers, Celery tasks, and Typer CLI — not four. modern-di, sync-by-design: https://modern-di.modern-python.org"
187201
- "Dual-write problem in your event-driven service? faststream-outbox does the transactional outbox for FastStream + Postgres in one decorator."
188-
- "httpx, but your 404s are typed exceptions and retry/bulkhead/circuit-breaker are composable middleware. httpware."
202+
- "An HTTP client framework where your 404s are typed exceptions and retry/bulkhead/circuit-breaker are composable middleware. Sync and async. httpware."
189203

190204
---
191205

0 commit comments

Comments
 (0)