<@ULVA73B9P> I am using the self-hosted instance ...
# ask-marvin
s
@Marvin I am using the self-hosted instance with Prefect v3.6.x. I noticed that the prefect folder under
~/.prefect/storage
is using a lot of inodes on my $HOME. How can I manage where persistent store is saved, choosing a different location, and please provide the purpose of the
~/.prefect/storage
directory.
m
thought for 138.4 seconds
Yes — in Prefect 3.6.x,
~/.prefect/storage
is typically the default local results storage directory. What
~/.prefect/storage
is for
By default, Prefect uses
~/.prefect
as its local home directory. Inside that: -
~/.prefect/storage
stores persisted flow/task results on the local filesystem -
~/.prefect/prefect.db
is often the default SQLite database for a local/self-hosted server setup -
~/.prefect/profiles.toml
stores Prefect profiles/config -
~/.prefect/memo_store.toml
is used for server memoization/cache behavior - some other runtime/server support files may also live under
~/.prefect
So if you are seeing lots of inode usage specifically under
~/.prefect/storage
, that usually means Prefect is persisting many results as many small files. How to move it somewhere else You have two main options: Option 1: Move all of Prefect’s local home directory Set
PREFECT_HOME
to a different path. This changes the root for things like
storage
, profiles, SQLite DB, etc.
Copy code
bash
export PREFECT_HOME="/path/with/more/inodes/prefect-home"
Or persist it in your current Prefect profile:
Copy code
bash
prefect config set PREFECT_HOME="/path/with/more/inodes/prefect-home"
That would make the default storage path become:
Copy code
text
/path/with/more/inodes/prefect-home/storage
Option 2: Move only the local results storage directory If you only want to relocate the persisted results store, set:
Copy code
bash
export PREFECT_RESULTS_LOCAL_STORAGE_PATH="/path/with/more/inodes/prefect-results"
Or:
Copy code
bash
prefect config set PREFECT_RESULTS_LOCAL_STORAGE_PATH="/path/with/more/inodes/prefect-results"
There is also a legacy-compatible env var alias:
Copy code
bash
export PREFECT_LOCAL_STORAGE_PATH="/path/with/more/inodes/prefect-results"
Config file form If you use
prefect.toml
, this is the relevant setting:
Copy code
toml
[results]
local_storage_path = "/path/with/more/inodes/prefect-results"
And for the home directory:
Copy code
toml
home = "/path/with/more/inodes/prefect-home"
Which one should you use? - Use
PREFECT_HOME
if you want to move everything under
~/.prefect
- Use
PREFECT_RESULTS_LOCAL_STORAGE_PATH
if the inode issue is specifically from persisted results in
storage
Important note for self-hosted server If you are running a self-hosted Prefect server and also using the default SQLite DB, moving only
storage
will not move
prefect.db
. If
$HOME
pressure is broader than just inodes from result files, consider moving
PREFECT_HOME
or explicitly moving your DB off
$HOME
too. Why inode usage can get high there This usually happens when: - result persistence is enabled - many task runs/flow runs are producing persisted outputs - outputs are stored as lots of separate small files If you want, I can also help you with: - identifying why so many files are being written - reducing result persistence - safely cleaning old contents from
~/.prefect/storage
in a self-hosted setup Useful docs/app references: - Prefect settings and profiles: https://docs.prefect.io/ - Prefect CLI config usage: https://docs.prefect.io/ - Prefect app/server context: https://docs.prefect.io/ If you want, I can give you a quick checklist for migrating an existing self-hosted instance from
~/.prefect/storage
to a new filesystem path safely.
s
@Marvin Please elaborate on these three:
Copy code
If you want, I can also help you with:
- identifying why so many files are being written
- reducing result persistence
- safely cleaning old contents from ~/.prefect/storage in a self-hosted setup
m
thought for 162.5 seconds
Absolutely — here’s what those three usually mean in practice for Prefect 3.6.x. 1. Identifying why so many files are being written In most cases, lots of files under
~/.prefect/storage
means results are being persisted locally. That can happen when one or more of these are true: - a flow or task is configured with
persist_result=True
- global result persistence is enabled - caching is enabled on tasks - a default result storage block/path is configured and your runs are writing there - you have many short-lived task runs, each producing its own persisted result file Important behavior: in Prefect 3.x, local result storage is generally used for persisted results, not for all orchestration metadata. Orchestration metadata lives in the API database, not in
storage
. What to inspect first 1. Check your settings 2. Check your code for
persist_result
/ caching 3. Check file growth patterns in the directory A practical checklist:
Copy code
bash
prefect config view
Look for settings related to results, especially whether you have configured any of: -
PREFECT_RESULTS_PERSIST_BY_DEFAULT
-
PREFECT_RESULTS_LOCAL_STORAGE_PATH
-
PREFECT_LOCAL_STORAGE_PATH
-
PREFECT_DEFAULT_RESULT_STORAGE_BLOCK
Also search your codebase for:
Copy code
bash
grep -R "persist_result" .
grep -R "cache_policy" .
grep -R "result_storage" .
grep -R "result_storage_key" .
Why this matters: -
persist_result=True
on a flow can cause many task results in that flow to be stored -
cache_policy=...
usually implies persisted results are needed for cache reuse - many small task outputs can create lots of tiny files, which consumes inodes quickly even if disk bytes are modest You can also inspect the filesystem itself:
Copy code
bash
du -sh ~/.prefect/storage
find ~/.prefect/storage -type f | wc -l
find ~/.prefect/storage -type f | head
find ~/.prefect/storage -type f -printf '%TY-%Tm-%Td %TT %p\n' | sort | tail
That helps answer: - how many files exist - whether they are actively still being created - whether this is old buildup or ongoing write behavior If you want a stronger diagnosis, the next thing I’d ask is: - are you explicitly using task caching? - do your flows/tasks set
persist_result=True
anywhere? - are you using local storage intentionally, or did it happen implicitly? 2. Reducing result persistence There are a few ways to reduce file creation, depending on whether you still need persisted results. Option A: Disable persistence unless you truly need it At the flow/task level:
Copy code
python
from prefect import flow, task

@task(persist_result=False)
def my_task():
    return 42

@flow(persist_result=False)
def my_flow():
    return my_task()
This is the most direct way to prevent local result files for those runs. Option B: Avoid task caching if you do not need it If you have tasks with caching, Prefect needs persisted results to reuse them across runs. So caching can be a major reason files accumulate. For example, if you have something like:
Copy code
python
from prefect import task
from prefect.cache_policies import INPUTS

@task(cache_policy=INPUTS)
def compute(x):
    return x * 2
that can lead to persisted result files for cache entries. If cache reuse is not important, remove or reduce caching. Option C: Persist only selected tasks Instead of persisting broadly, persist only the expensive outputs you actually want to reuse or inspect:
Copy code
python
from prefect import flow, task

@task(persist_result=False)
def cheap_step():
    return "small temp value"

@task(persist_result=True)
def expensive_step():
    return {"important": "output"}

@flow(persist_result=False)
def my_flow():
    a = cheap_step()
    b = expensive_step()
    return b
That pattern usually reduces inode growth substantially. Option D: Move persisted results to a different backend If you do need persistence, but don’t want millions of files under
$HOME
, point results elsewhere:
- a different local filesystem path with more inode capacity - object storage such as S3/GCS/Azure, if that fits your setup For local path only:
Copy code
bash
export PREFECT_RESULTS_LOCAL_STORAGE_PATH="/data/prefect-results"
or:
Copy code
bash
prefect config set PREFECT_RESULTS_LOCAL_STORAGE_PATH="/data/prefect-results"
If your concern is specifically inode pressure on
$HOME
, this is often the simplest operational fix. Option E: Revisit whether flow/task return values need persistence at all A common anti-pattern is returning large or numerous intermediate objects when they are only needed transiently within the same run. If they do not need to be resumed, cached, or inspected later, avoid persisting them. 3. Safely cleaning old contents from
~/.prefect/storage
Short version: yes, you can clean it, but you should treat it as deleting persisted results/cache data, not as deleting harmless temp files. Deleting files there can affect: - cache hits for tasks - retrieval of stored results from older runs - any flow/task behavior that expects the persisted result still to exist So “safe” depends on your usage. Generally safe when: - you do not rely on old cached task results - you do not need to re-read old persisted outputs - you are cleaning results from completed historical runs only - you take a backup first if unsure Less safe when: - you actively use task caching across runs - you have long-running or resumable workflows depending on stored results - another component expects those result files to remain available - you are deleting files for currently active or very recent runs A practical cleanup approach Step 1: Back it up first
Copy code
bash
cp -r ~/.prefect/storage ~/.prefect/storage.backup.$(date +%Y%m%d-%H%M%S)
or tar it:
Copy code
bash
tar -czf ~/prefect-storage-backup-$(date +%Y%m%d-%H%M%S).tar.gz ~/.prefect/storage
Step 2: Start with old files only For example, inspect files older than 30 days:
Copy code
bash
find ~/.prefect/storage -type f -mtime +30 | head
find ~/.prefect/storage -type f -mtime +30 | wc -l
Then delete only those if that matches your retention goal:
Copy code
bash
find ~/.prefect/storage -type f -mtime +30 -delete
That is much safer than wiping the entire directory. Step 3: Recheck behavior After cleanup: - run a representative flow - confirm task execution still behaves as expected - confirm you are okay with cache misses on deleted results Step 4: Automate retention if needed If this buildup is recurring, it’s better to establish a retention policy than to do emergency cleanup later. Example weekly cleanup:
Copy code
bash
find /path/to/prefect-results -type f -mtime +30 -delete
Run that from cron/systemd timer on the machine hosting the storage. What I would recommend operationally Given your inode issue, the best sequence is usually: 1. Move the storage path off
$HOME
using
PREFECT_RESULTS_LOCAL_STORAGE_PATH
2. Audit why persistence is happening (
persist_result
, caching, result settings) 3. Reduce unnecessary persistence 4. Add age-based cleanup for old files That way you solve both the immediate inode pressure and the long-term growth pattern. A few cautions - Don’t delete
~/.prefect/prefect.db
unless you intend to remove/reset your local SQLite-backed server database - Don’t assume
storage
is just temp data; it may hold results you still care about - If you use a shared/self-hosted environment, make sure all relevant processes see the same configured storage path If you want, I can help with either of these next: 1. a diagnostic checklist to determine exactly why your instance is persisting so many results, or 2. a recommended config pattern for self-hosted Prefect 3.6.x that minimizes inode usage.