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

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.1
File Size Uploaded
faultlib-1.2.1.tar.gz 76.0 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for faultlib 1.2.1
File Interpreter ABI Platform
faultlib-1.2.1-cp314-abi3-win_amd64.whl CPython 3.14 abi3 Windows x86-64 Details
faultlib-1.2.1-cp314-abi3-manylinux_2_34_x86_64.whl CPython 3.14 abi3 Linux glibc 2.34+ x86-64 Details
faultlib-1.2.1-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.1.tar.gz

Download URL faultlib-1.2.1.tar.gz
Size 76.0 kB
Tags Source
SHA-256 checksum
How to use checksums
eb52ce387d2c5b3569d3a52baeed483d1680ce3b225d0ff545153b4adc20f37f
BLAKE2b-256 checksum
How to use checksums
84fc8959e9d2f01a51bf4bb85f10e9aa4e322a6e98800a10815f6b0e3f56167e
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.1-cp314-abi3-win_amd64.whl

Download URL faultlib-1.2.1-cp314-abi3-win_amd64.whl
Size 652.8 kB
Tags CPython 3.14 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
75cfbe82646d72514366d5869b32c77676edb7a09ca8288213ffa0fc5f4e1598
BLAKE2b-256 checksum
How to use checksums
3d548c14b3406371c88d2028dc60f16ba21675359d0211f0bd8787e388e28d87
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.1-cp314-abi3-manylinux_2_34_x86_64.whl

Download URL faultlib-1.2.1-cp314-abi3-manylinux_2_34_x86_64.whl
Size 854.5 kB
Tags CPython 3.14 Linux glibc 2.34+ x86-64 abi3
SHA-256 checksum
How to use checksums
f2b4beeb2d3336e38ac8a2035fb6344cf087e3207d446bfe1c5c2f877cdcfcc6
BLAKE2b-256 checksum
How to use checksums
829161f68a4cd974c9561f05d651506df939a5dbe641ca4c584a117b3181bdd3
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.1-cp314-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl

Download URL faultlib-1.2.1-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
54d6b8ba1f23c1e7f3de3c94258e133df4962f08f68ce9fd1a70f521306627c7
BLAKE2b-256 checksum
How to use checksums
ee720832a4689d615c50d0419f388da0fb8e867c3407e6351959fcbafa818ae7
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

This release

1.2.1 This release

4 release files

1.2.0

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