Jashaul
10/13/2025, 7:55 PMMarvin
10/13/2025, 7:55 PMMarvin
10/13/2025, 7:59 PMimport asyncio
from datetime import datetime, timedelta, timezone
from prefect.client.orchestration import get_client
from prefect.client.schemas import filters, sorting
# Configure how far back to retain
DAYS_TO_KEEP = 30
async def main():
cutoff = datetime.now(timezone.utc) - timedelta(days=DAYS_TO_KEEP)
async with get_client() as client:
# Page through runs to avoid loading everything at once
page_size = 500
page = 1
total_deleted = 0
while True:
runs = await client.read_flow_runs(
flow_runs_filter=filters.FlowRunFilter(
# only runs that started before cutoff (you could also use end_time)
start_time=filters.FlowRunFilterStartTime(before=cutoff),
# optional: skip active runs
state_type=filters.FlowRunFilterStateType(any_=["COMPLETED", "FAILED", "CANCELLED", "CRASHED"])
),
sort=sorting.FlowRunSort.START_TIME_ASC,
limit=page_size,
offset=(page-1)*page_size,
)
if not runs:
break
for fr in runs:
try:
await client.delete_flow_run(fr.id)
total_deleted += 1
except Exception as exc:
print(f"Failed to delete {fr.id}: {exc}")
page += 1
print(f"Deleted {total_deleted} flow runs older than {DAYS_TO_KEEP} days.")
if __name__ == "__main__":
asyncio.run(main())
- Make sure your script can reach your server (e.g., PREFECT_API_URL is set).
- Docs: API reference: flow_runs and Filters
One-off via CLI (per-ID):
- We verified this command exists:
prefect flow-run delete <FLOW_RUN_ID>
- You can list runs to find IDs:
prefect flow-run ls --limit 100
- There isn’t a built-in bulk delete in the CLI, so for large purges use the Python client script above.
Option B: Delete only logs (keep runs)
- There isn’t a public CLI command to delete logs only. While the server’s internal models support log deletion, there’s no public endpoint exposed for it in the API module.
- If you truly need to keep runs but drop older logs, you can do it directly in Postgres. Proceed with caution and take a backup first.
- The exact table name may be log or logs depending on version; you can check which exists:
SELECT to_regclass('public.log') AS log_exists, to_regclass('public.logs') AS logs_exists;
- Example (adjust table name and timestamp column as found in your schema; typically log and timestamp):
BEGIN;
-- Delete logs older than 30 days
DELETE FROM log WHERE timestamp < NOW() - INTERVAL '30 days';
-- Reclaim space and update stats (optional but recommended)
VACUUM ANALYZE log;
COMMIT;Marvin
10/13/2025, 7:59 PMprefect server database reset
- Verified command group:
prefect server database --help
Notes and best practices
- There is no out-of-the-box “retention policy” toggle in Prefect 3.x for auto-purging. Most teams schedule a maintenance flow using Option A.
- Test on a staging DB or with a small cutoff first.
- Back up your database before large deletes.
If you share:
- Your Prefect version (2.x vs 3.x),
- Whether you want to remove runs+logs or logs only,
- Your retention window,
I can tailor a ready-to-run script or SQL for your setup.