Skip to main content

faultlib

faultlib is the Python interface to the Rust fault network fault-injection engine. It runs TCP and UDP proxies inside an asyncio application, applies ordered fault chains, and exposes typed progress, status, TCP-stream, and UDP-exchange records.

Use it when network degradation is one part of a larger Python experiment—for example, adding database latency while restarting a pod and observing service recovery. For shell-driven experiments, use the fault CLI.

Python is a thin binding: validation, phase lifecycle, scheduling decisions, events, defaults, and errors remain canonical Rust behavior, shared with the TypeScript package through the fault-binding crate. The package adds typed Python mappings and dataclasses, not a second fault model.

Requirements and installation

faultlib requires Python 3.14 or newer.

python -m pip install faultlib

Start a proxy

import asyncio

from faultlib import Engine, Run


RUN: Run = {
    "schema_version": 1,
    "name": "slow database",
    "proxies": [
        {
            "name": "database",
            "protocol": "tcp",
            "listen": "127.0.0.1:15432",
            "upstream": "database.internal:5432",
        }
    ],
    "phases": [
        {
            "name": "degraded for thirty seconds",
            "duration": "30s",
            "proxies": [
                {
                    "proxy": "database",
                    "faults": [
                        {
                            "type": "latency",
                            "flow": "both",
                            "distribution": {
                                "type": "normal",
                                "mean_ms": 200.0,
                                "stddev_ms": 20.0,
                            },
                        }
                    ],
                }
            ],
        }
    ],
}


async def main() -> None:
    async with Engine(RUN) as engine:
        print(f"proxy listening on {engine.endpoints.tcp[0]}")
        result = await engine.run()

    print(f"run outcome: {result.outcome.kind}")


asyncio.run(main())

Point the application at 127.0.0.1:15432 for the duration of the experiment. The proxy forwards the connection to database.internal:5432; no database protocol support is required.

Run and its nested TypedDict types give type checkers the same shape as the published schema. Runtime results and events are frozen dataclasses rather than unstructured dictionaries.

Observe traffic

Engine.next_event() returns a completed transport record when one is available, a status event when none completes within status_interval seconds (two by default), and None once the engine stops:

from faultlib import StatusEvent, TcpStreamEvent, UdpExchangeEvent


async def observe(engine: Engine) -> None:
    while engine.alive():
        match event := await engine.next_event():
            case StatusEvent(status):
                print(
                    f"active={status.tcp.active} "
                    f"impacted={status.tcp.impacted}"
                )
            case TcpStreamEvent(stream):
                print(stream.stream_id, stream.outcome)
            case UdpExchangeEvent(exchange):
                print(exchange.exchange_id, exchange.outcome)
            case None:
                return

Record delivery is bounded and best effort. A slow Python consumer never stalls the Rust proxy. Aggregate status remains complete and reports omitted records through dropped_records.

Adapt a running experiment

engine.schedule() exposes Rust-owned phase controls to Python. You can add, modify, delete, start, or stop future phases while ordinary Python tasks coordinate the surrounding system. A phase becomes immutable once it starts; invalid mutations raise PhaseStateError. Invalid arguments, such as a malformed duration or phase id, or a negative position, raise ValueError.

The complete example in the repository demonstrates engine events, adaptive scheduling, and bounded record retention: examples/python_proxy.py.

Supported behavior

  • TCP: latency, jitter, bandwidth, blackhole, connection reset
  • UDP: latency, jitter, directional blackhole
  • DNS over UDP: delay, timeout, truncation, refusal, SERVFAIL, NXDOMAIN, empty answers, and random A records

See the guide for realistic failure scenarios and the generated field reference for the exact wire contract.

Local development

From a checkout of the repository:

uv sync --project fault-python --python 3.14 --reinstall-package faultlib
uv run --project fault-python --python 3.14 python examples/python_proxy.py
uv run --project fault-python --python 3.14 ruff check \
  fault-python/python examples

Repeat uv sync --reinstall-package faultlib after changing Rust binding code.

Licensed under the Apache License 2.0.

Metadata

Release files for faultlib 1.2.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 faultlib 1.2.0
File Size Uploaded
faultlib-1.2.0.tar.gz 76.0 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for faultlib 1.2.0
File Interpreter ABI Platform
faultlib-1.2.0-cp314-abi3-win_amd64.whl CPython 3.14 abi3 Windows x86-64 Details
faultlib-1.2.0-cp314-abi3-manylinux_2_34_x86_64.whl CPython 3.14 abi3 Linux glibc 2.34+ x86-64 Details
faultlib-1.2.0-cp314-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl CPython 3.14 abi3 macOS 10.12+ universal2 (ARM64, x86-64), macOS 10.12+ x86-64, macOS 11.0+ ARM64 Details

Total release size: 3.1 MB

Release files / faultlib-1.2.0.tar.gz

Download URL faultlib-1.2.0.tar.gz
Size 76.0 kB
Tags Source
SHA-256 checksum
How to use checksums
4f123e224e3bd189a9013ef4eba8f5ee9189e25788698d09a559c61663ee47b2
BLAKE2b-256 checksum
How to use checksums
5561223cbc1abd3f3ef1526940bd9f87999e86b1e3e6de73838e62b0bbbcf090
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 8, 2026.

Transparency log

Release files / faultlib-1.2.0-cp314-abi3-win_amd64.whl

Download URL faultlib-1.2.0-cp314-abi3-win_amd64.whl
Size 652.8 kB
Tags CPython 3.14 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
e9d3720420ad2fd8ca4cf0c09f87b8416b6022bbd2a45e5723c18680ad514c76
BLAKE2b-256 checksum
How to use checksums
695f92c445f78e7fa4cc1d4be4b8233f7e3b56f6c909f148e30c978db0085068
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 8, 2026.

Transparency log

Release files / faultlib-1.2.0-cp314-abi3-manylinux_2_34_x86_64.whl

Download URL faultlib-1.2.0-cp314-abi3-manylinux_2_34_x86_64.whl
Size 854.4 kB
Tags CPython 3.14 Linux glibc 2.34+ x86-64 abi3
SHA-256 checksum
How to use checksums
232facec5e0370483a4972bd93b5f91803fb6ee7eebbd10dc942497e7a550316
BLAKE2b-256 checksum
How to use checksums
31aa6f555a2f09bb24dcc962a6a0d053fd5e8aac7494f58195c4ff18d9f2abd1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 8, 2026.

Transparency log

Release files / faultlib-1.2.0-cp314-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl

Download URL faultlib-1.2.0-cp314-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl
Size 1.5 MB
Tags CPython 3.14 abi3 macOS 10.12+ universal2 (ARM64, x86-64) macOS 10.12+ x86-64 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
2eac17a0747bf7af8ec8283c05781dc0ec06b2514f63eca5fec171d4a6b229f2
BLAKE2b-256 checksum
How to use checksums
7004b8aa6a1020793e9896fda31c1ff3599e4e461e9596e8f0a3562b2c5c0d98
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Oct 8, 2026.

Transparency log

Release history Release notifications | RSS feed

1.2.1

4 release files

This release

1.2.0 This release

4 release files

1.1.0

4 release files

1.0.0

4 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