Commit 5f8011c
authored
docs: production Python article series (#6)
* docs: open the production Python article series with an editorial backlog
* docs: plan the full year of posts, 48 in seven series
* docs: drop the publishing calendar, posts are written in order and merged when done
* docs: reserve wording
* docs: timeouts are not deadlines, post 1 of the series
* docs: post 1 waits for clientwright #24 and #25
* docs: house rule, bugs found while measuring are fixed before the post continues
* docs: shutdown lab scripts for post 3
* docs: plan status for posts 2 and 3
* docs: idempotency lab script for post 4
* docs: the five migration tests every Python project should run in CI, post 2
* docs: we started writing documentation for AI coding agents, post 7
* docs: post 7, claims the pages support
* docs: pgbouncer lab scripts for post 8
* docs: graceful shutdown in Kubernetes is a protocol, post 3
* docs: post 1 measured against clientwright 0.2.2, caveat gone
* docs: safe gRPC retries, post 10
* docs: why I stopped wrapping HTTP clients, post 5
* docs: twelve libraries, one engineering standard, post 12
* docs: what every production Python microservice reimplements, post 11
* docs: exactly-once effects lab script for post 6
* docs: PgBouncer transaction mode and async SQLAlchemy, post 8
* docs: idempotency keys, the part everyone gets wrong, post 4
* docs: retries can make an outage worse, post 13
* docs: one lifecycle for HTTP, gRPC, workers and cron jobs, post 15
* docs: exactly-once is a lie, exactly-once effects are not, post 6
* docs: circuit breakers should be per origin, post 17
* docs: the unit of work pattern in SQLAlchemy 2, post 21
* docs: Retry-After, backoff and jitter, post 18
* docs: gRPC channels should not be pooled by address alone, post 20
* docs: Redis fail-open lab scripts for post 22
* docs: Kafka-down outbox lab script for post 24
* docs: transactional inbox, the other half of the outbox pattern, post 16
* docs: why application lifecycle should not belong to FastAPI, post 19
* docs: AI code review should not be fully autonomous, post 23
* docs: testing database migrations with Testcontainers, post 14
* docs: schema drift variants and the three extra checks, for post 27
* docs: pool metrics lab for post 34; post 8 names the held-time histogram correctly
* docs: when should Redis fail open, post 22
* docs: post 8, drop the forward link until post 34 exists
* docs: idempotency for background jobs and Kafka consumers, post 30
* docs: graceful Kafka consumer shutdown in Kubernetes, post 32
* docs: Redis health lab script for post 35
* docs: partition-existing-table lab script for post 25
* docs: gRPC interceptor lab scripts for post 33
* docs: aiokafka checklist lab scripts for post 26
* docs: update editorial backlog statuses
* docs: production gRPC server lab for post 28
* docs: post 28, the anatomy of a production gRPC server
* docs: post 29, stop passing AsyncSession everywhere
* docs: post 27, schema drift and what CI would notice
* docs: post 35, Redis health checks beyond PING
* docs: post 24, an outbox through a broker outage
* docs: post 34, what to monitor in a connection pool
* docs: post 26, the production checklist for aiokafka
* docs: partition retention lab for post 31
* docs: post 31, partition retention is not DROP TABLE
* docs: warmup/readiness/liveness lab for post 37
* docs: post 37, warmup readiness and liveness
* docs: transport-independent errors lab for post 38
* docs: mark post 38 blocked on servicewright #50
* docs: post 33, gRPC interceptors and streaming RPCs
* docs: UUIDv7 partition key lab for post 44
* docs: post 44, UUIDv7 as a partition key
* docs: topic creation lab for post 41
* docs: post 41, who creates Kafka topics
* docs: post 45, publishing to PyPI without API tokens
* docs: post 25, partitioning an existing table
* docs: backlog statuses for posts 46 and 47
* docs: reliability lab for post 47
* docs: post 47, reliability is not retry=3
* docs: backlog statuses for posts 40 and 48
* docs: idempotency chain lab for post 40
* docs: post 40, idempotency across a chain
* docs: post 38, transport-independent errors
* docs: exception mapping lab for post 43
* docs: post 43, mapping exceptions to gRPC status codes
* docs: pg_partman adoption lab for post 39
* docs: post 39, migrating from pg_partman
* docs: note what the three AI-tooling posts still need
* docs: post 48, how I start a Python library
* docs: dependency footprint lab for post 46
* docs: post 46, zero-dependency cores
* docs: defer the three AI-tooling posts
* docs: illustrate every blog card, light and dark
Each post gets a flat isometric illustration built from a shared vocabulary of
domain objects -- partition slabs under a parent bar, an append-only log trough,
a key-value rack, channel tubes, a connection pool -- so a card says what its
post is about before the title is read.
The dark-scheme file is the same drawing with the lightness ramp inverted, the
way logo-dark.svg relates to logo.svg, rather than a separate illustration.
Cards are matched by the slug in their href, so no listing markup changes.
* docs: open every post with its illustration
The hero is a background on a div, not an <img>: the theme toggle sets
data-md-color-scheme on the root, which a stylesheet can follow and a
<picture> media query cannot, so this is what swaps the light and dark
renders together with the rest of the page.
A background carries no alt text, so the div declares role="img" and takes
its accessible name from the one-line idea the illustration was drawn from.
* docs: keep the illustration prompts and toolchain in the repo
The card and hero images were reproducible only on one laptop: the prompts
they were drawn from and the scripts that render, colour-correct, derive the
dark variant and wire them into the stylesheet lived outside version control.
Sits at the repo root rather than under docs/, where 49 markdown prompts would
each have become a published page. The renders stay ignored -- 450 MB of PNG
rebuilt from the prompts; what the site serves is the webp in docs/assets/blog.
* docs: drop the internal gateway path from the image generator
The generator carried a second way to reach the API: an egress proxy read out
of an application .env, with an upstream token map and a forwarding header.
That is one company's internal routing, and it does not belong in a public
repository -- --base-url already covers any OpenAI-compatible endpoint.
* Enhance documentation and tooling structure
- Revamped the tools documentation page to provide a clearer overview of developer tools, emphasizing their self-hosted and open-source nature.
- Updated footer links for consistency and clarity in navigation.
- Introduced a new script to build the blog catalog and its search data from Markdown front matter, improving article organization and searchability.
- Added new CSS and JavaScript files for better styling and functionality of the blog explorer, libraries, and tools sections.
- Modified navigation labels for improved user experience in the blog section.
* docs: add internationalization proposal for English and Russian editions1 parent 437ee8b commit 5f8011c
400 files changed
Lines changed: 22097 additions & 662 deletions
File tree
- .github/workflows
- docs
- assets/blog
- blog
- archive
- category
- lab
- 2026-09-06-timeouts-are-not-deadlines
- 2026-09-07-aiokafka-checklist
- 2026-09-07-circuit-breakers-per-origin
- 2026-09-07-exactly-once-effects
- 2026-09-07-five-alembic-migration-tests
- migrations
- versions
- bad_name
- clean
- drift_check_missing
- drift_enum_value
- drift_extra_column
- drift_index_missing
- drift_server_default
- drift_type
- drift
- enum_leftover
- two_heads
- wrong_name_in_downgrade
- shop
- tests
- 2026-09-07-graceful-shutdown
- 2026-09-07-grpc-channel-identity
- 2026-09-07-grpc-interceptors-and-streams
- 2026-09-07-idempotency-across-a-chain
- 2026-09-07-idempotency-for-jobs-and-consumers
- 2026-09-07-idempotency-keys
- 2026-09-07-kafka-consumer-shutdown
- 2026-09-07-lifecycle-not-fastapi
- 2026-09-07-migrating-from-pg-partman
- 2026-09-07-one-lifecycle
- 2026-09-07-partition-existing-table
- 2026-09-07-partition-retention
- 2026-09-07-pgbouncer-async-sqlalchemy
- 2026-09-07-production-grpc-server
- 2026-09-07-python-exceptions-to-grpc-status-codes
- 2026-09-07-redis-health-checks
- 2026-09-07-reliability-is-not-retry-3
- 2026-09-07-retry-after-backoff-jitter
- 2026-09-07-retry-budget
- 2026-09-07-safe-grpc-retries
- 2026-09-07-sqlalchemy-pool-metrics
- 2026-09-07-stop-passing-asyncsession-everywhere
- 2026-09-07-topics-on-startup
- 2026-09-07-transactional-inbox
- 2026-09-07-transport-independent-errors
- 2026-09-07-twelve-libraries-one-standard
- 2026-09-07-unit-of-work-sqlalchemy-2
- 2026-09-07-uuidv7-partition-key
- 2026-09-07-warmup-readiness-liveness
- 2026-09-07-what-every-microservice-reimplements
- 2026-09-07-when-kafka-is-down
- 2026-09-07-when-should-redis-fail-open
- 2026-09-07-why-i-stopped-wrapping-http-clients
- 2026-09-07-zero-dependency-cores
- posts
- javascripts
- libraries
- stylesheets
- tools
- illustrations
- overrides/partials
- plans
- scripts
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
19 | 20 | | |
20 | 21 | | |
21 | 22 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
4 | 4 | | |
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
11 | 14 | | |
12 | 15 | | |
13 | | - | |
| 16 | + | |
14 | 17 | | |
15 | 18 | | |
16 | 19 | | |
| |||
0 commit comments