
The old layout for our Simple Facts library was six Prefect deployments, flat, with no hierarchy:
discover-network · collect-facts · sync-to-netbox
test-netbox · netbox-status · purge-netboxFunctional, but three problems kept surfacing:
test-netbox was never a real workflow step — it was a preflight check masquerading as a first-class deployment.The new layout is five deployments, grouped by purpose:

Pipeline:
discover-and-collect ← one click
discover-only
collect-only
sync-to-netbox ← mandatory NetBox preflight + postflight
Admin:
purge-netbox ← dry-run by default, same preflight/postflightThis was the interesting discovery. We expected to refactor NetworkDiscovery, FactCollector, or the NetBox sync pipeline. We didn’t touch any of them.
What actually changed:
discover_network_flow() and collect_facts_flow() as subflows.get_netbox_status() call before the mutation and another after.test_netbox_connection duplicates what get_netbox_status already does).The core library — device discovery, fact collection, NetBox sync, VRF handling, MAC de-duplication — is byte-for-byte the same as it was before.
Diff shape:
13 files changed, +800 / −439Most of those +800 lines are documentation, a design blueprint, and an expanded CHANGELOG. The actual behavioral change fits in maybe 80 lines of Python.
discover-and-collect is a single deployment in the UI, but when you click it you see the parent run plus both child runs with their own artifacts, logs, and timings. The ergonomics of “one button” with none of the opacity of “one giant flow.”skip_preflight flag. The reasoning: an escape hatch on a safety check just becomes the default when someone is in a hurry. If an operator truly needs to bypass (e.g., status endpoint is broken but writes still work), they can call the flow function directly from Python — a deliberate friction budget.The most satisfying refactors are the ones where you don’t touch the hard parts. The sync logic is gnarly, vendor-specific, full of edge cases — and it didn’t need to change at all. The fix was one layer up: how the work is presented to the operator.
Five deployments, a wrapper flow, mandatory safety rails, and an automatic audit trail. The machinery underneath kept working exactly as before, but the surface it exposes is now harder to misuse and easier to reason about.
Sometimes the best library change is a better front door.
Ship notes: v2.4.0 on PyPI · refactor(prefect): consolidate to 5 deployments with mandatory preflight/postflight