Skip to main content

Dynamic DES

CI Pipeline Documentation PyPI version Python Versions License: MIT

Realistic event streams from a simulation you can steer while it runs.

Dynamic DES architecture

Most test data generators write random rows. Dynamic DES writes the events of a working process: orders queue for staff, machines slow down, and a backlog builds when arrivals outpace capacity. The data has the cause and effect of a real system, because it comes from a SimPy discrete-event simulation.

Change an arrival rate or a capacity while the simulation runs, from Kafka, Redis, PostgreSQL or a timed scenario, and the pipeline downstream sees the effect. One run can write a week of history at full speed, then keep streaming in real time.

Events and telemetry go to Kafka, Redis, PostgreSQL, Parquet or JSONL files (on local disk or S3-compatible storage), or Apache Iceberg tables. A model is a YAML file, a Python builder, or SimPy code.

Used for: testing streaming pipelines with data that behaves like production, demos and workshops, digital twins that follow live data, and training data for models that predict delays or load.

The control dashboard changes simulation parameters while a run is going, and the telemetry reacts without a restart:

Live parameter updates from the control dashboard

Key Features

  • Real time or full speed: DynamicRealtimeEnvironment runs SimPy in step with the system clock, or unpaced, and reports how far the simulation lags behind real time.
  • Live parameters: arrival rates, service times and capacities change mid-run through registry paths such as Line_A.arrival.standard.rate. A resource grows at once, and shrinks only as busy units are released, so no work in progress is lost.
  • Several sinks per run: each sink added with add_egress has its own when filter, batch_size and flush_interval, so one run can feed a stream and a data lake together.
  • Backfill then go live: one run generates backdated history at full speed, then switches to real time at go_live_at.
  • Three ways to write a simulation: the low-level DynamicRealtimeEnvironment, the declarative SimulationContext builder, or a YAML blueprint run with ddes run.
  • Serialisation: JSON through orjson by default, Avro through the Confluent or AWS Glue Schema Registry for chosen topics, and Pydantic models published as they are.
  • Kafka security: extra keyword arguments go to the Kafka client, so SASL, mTLS, OAuth and AWS IAM clusters work.

Installation

Install the core library with uv or pip.

With uv:

# The ddes command
uv tool install dynamic-des

# Or the library, in a uv project
uv add dynamic-des

With pip:

pip install dynamic-des

The connectors are optional extras, for example uv add "dynamic-des[kafka,parquet]" or pip install "dynamic-des[kafka,parquet]":

Extra Adds
kafka Kafka ingress and egress
confluent Avro with the Confluent Schema Registry (includes kafka)
glue Avro with the AWS Glue Schema Registry (includes kafka)
redis Redis ingress and egress
postgres PostgreSQL ingress and egress
parquet Parquet and JSONL files on local disk or S3-compatible storage
iceberg Apache Iceberg tables through a REST catalog
all Every extra above

Run an Example

Every example is written three ways: as a YAML blueprint, with the declarative API and with the low-level API. The local example needs no container. Here is its YAML version:

ddes examples get downloads the example at the release you install, into a folder of its own. Pick uv or pip:

With uv

# 1. Install
uv tool install dynamic-des

# 2. Download the example
ddes examples get local --api yaml
cd local/yaml

# 3. Run it
ddes run local.yaml

With pip

# 1. Install
pip install dynamic-des

# 2. Download the example
ddes examples get local --api yaml
cd local/yaml

# 3. Run it
ddes run local.yaml

For the declarative or low-level version, use --api declarative or --api low-level; the Installation page shows all three in tabs. ddes examples lists the other examples, and each example page gives the same steps, including the odctl service it needs.

Three Ways to Write a Simulation

A simulation can be a YAML blueprint, a script using the declarative API (SimulationContext), or a script using the low-level API (DynamicRealtimeEnvironment and SimPy processes). All three build the same parameters and run on the same environment, so the registry paths, the records and the connectors are the same whichever way you choose.

This blueprint is a small factory: one lathe, a part about every 2 seconds and 1.5 seconds of machining, with every record printed to the terminal:

# The First Simulation tutorial: the factory as a blueprint.
# Run it with: ddes run first_factory.yaml
simulation:
  sim_id: Factory_A
  factor: 1.0  # 1 simulated second takes 1 real second

resources:
  lathe: {current_cap: 1, max_cap: 1}

services:
  # With no std, a normal distribution returns its mean every time
  machining: {dist: normal, mean: 1.5}

arrivals:
  # One part every 2 seconds on average; each arrival spawns process_part
  parts: {dist: exponential, rate: 0.5, spawn: process_part}

tasks:
  process_part:
    service: machining
    resource: lathe
    # The finished event's value; id_field adds the task id as part_id
    payload: {}
    id_field: part_id

egress:
  - type: Console

run:
  until: 10

First Simulation builds this factory step by step, with the YAML, declarative and low-level code side by side at each step, and the comparison of the three ways explains which to choose.

Roadmap

  • Planned for 1.0: routing between tasks, entity state, more distributions, stores and containers, built-in statistics and ddes explain; a simulation server (ddes serve) with a REST API, a browser UI and schedules, run locally through odctl; a page in the docs for each new building block as it ships.
  • Future work: breakdowns and schedules, transport on maps, data-driven inputs, experiments and analysis, animation, generated values in YAML, more sinks and delivery faults.

The roadmap page has the details.

Learn More

The documentation is at jaehyeon.me/dynamic-des.

Blog posts about dynamic-des and the projects built on it are tagged dynamic-des on jaehyeon.me.

Projects that use dynamic-des:

  • benchtop: hands-on data engineering and machine learning demos that run locally, most of them with data produced by dynamic-des.
  • agentic-analytics-system: conversational analytics over an Iceberg lakehouse, with the lakehouse data generated by dynamic-des.
  • oml-digital-twin-hotrolling: a streaming digital twin of a steel hot rolling mill, with online machine learning on Kafka and Flink.

License

MIT

Metadata

Release files for dynamic-des 0.17.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 dynamic-des 0.17.0
File Size Uploaded
dynamic_des-0.17.0.tar.gz 80.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for dynamic-des 0.17.0
File Interpreter ABI Platform
dynamic_des-0.17.0-py3-none-any.whl Python 3 none any Details

Total release size: 178.5 kB

Release files / dynamic_des-0.17.0.tar.gz

Download URL dynamic_des-0.17.0.tar.gz
Size 80.6 kB
Tags Source
SHA-256 checksum
How to use checksums
a1707519db1aa1d7d820be2762e91a2edbc4af13be0838771aa3c8eb554fa36d
BLAKE2b-256 checksum
How to use checksums
bb9e9ed2153a3e90ec40d302fde4f7e0845daf9a6465a7deaaeea5c4bde32279
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 11, 2026.

Transparency log

Release files / dynamic_des-0.17.0-py3-none-any.whl

Download URL dynamic_des-0.17.0-py3-none-any.whl
Size 97.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a5090ebf20b682c0bc428d0cad9b902ca5a44d8ea185f4d84f9eeeafd2549b92
BLAKE2b-256 checksum
How to use checksums
40ba3adbc89a1233ec9a12f0e642e17b7c47cd409bfde6161bf0f37115c5046c
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 11, 2026.

Transparency log

Release history Release notifications | RSS feed

0.20.0

2 release files

0.19.0

2 release files

0.18.0

2 release files

This release

0.17.0 This release

2 release files

0.15.0

2 release files

0.14.0

2 release files

0.13.0

2 release files

0.12.0

2 release files

0.11.3

2 release files

0.11.2

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.0

2 release files

0.9.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.0

2 release files

0.2.0

2 release files

0.1.1

2 release files

0.1.0

2 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