Santiago Gutierrez
05/07/2026, 12:50 AM~/.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.Marvin
05/07/2026, 12:50 AMMarvin
05/07/2026, 12:53 AM~/.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.
bash
export PREFECT_HOME="/path/with/more/inodes/prefect-home"
Or persist it in your current Prefect profile:
bash
prefect config set PREFECT_HOME="/path/with/more/inodes/prefect-home"
That would make the default storage path become:
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:
bash
export PREFECT_RESULTS_LOCAL_STORAGE_PATH="/path/with/more/inodes/prefect-results"
Or:
bash
prefect config set PREFECT_RESULTS_LOCAL_STORAGE_PATH="/path/with/more/inodes/prefect-results"
There is also a legacy-compatible env var alias:
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:
toml
[results]
local_storage_path = "/path/with/more/inodes/prefect-results"
And for the home directory:
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.Santiago Gutierrez
05/07/2026, 1:03 AMIf 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 setupMarvin
05/07/2026, 1:03 AMMarvin
05/07/2026, 1:06 AM~/.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:
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:
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:
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:
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:
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:
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:Marvin
05/07/2026, 1:06 AMbash
export PREFECT_RESULTS_LOCAL_STORAGE_PATH="/data/prefect-results"
or:
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
bash
cp -r ~/.prefect/storage ~/.prefect/storage.backup.$(date +%Y%m%d-%H%M%S)
or tar it:
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:
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:
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:
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.