Shubham
07/08/2026, 6:21 PMMarvin
07/08/2026, 6:22 PMMarvin
07/08/2026, 6:26 PMbash
PREFECT_PROFILE='ephemeral'
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true'
For production style self-hosting, you should move to:
- PostgreSQL as the API database
- a non-ephemeral profile
- explicit server config
- ideally manual DB migrations before startup
Also, an important caveat:
Prefect does not provide an official built-in SQLite → PostgreSQL data migration tool.
So the safest supported path is:
1. back up your current SQLite DB
2. stand up PostgreSQL
3. point Prefect at PostgreSQL
4. initialize the schema with Prefect migrations
5. either:
- start fresh, or
- do a manual/custom data migration if you must keep history
Relevant docs:
- Self-hosting Prefect 3
- Prefect Server concepts
What I recommend for you
Since you’re on 3.6.15, I’d suggest a clean production cutover rather than trying to import SQLite tables directly unless preserving historical runs is mandatory.
---
1. Back up your current SQLite database
Your current local DB is typically here:
bash
~/.prefect/prefect.db
Back it up first:
bash
cp ~/.prefect/prefect.db ~/.prefect/prefect.db.backup
If you want an extra export:
bash
sqlite3 ~/.prefect/prefect.db ".dump" > ~/prefect_sqlite_dump.sql
---
2. Prepare PostgreSQL
Prefect 3 production guidance expects:
- PostgreSQL 14.9+
- pg_trgm extension enabled
Example in Postgres:
sql
CREATE DATABASE prefect;
CREATE USER prefect_user WITH PASSWORD 'strong-password';
GRANT ALL PRIVILEGES ON DATABASE prefect TO prefect_user;
\c prefect
CREATE EXTENSION IF NOT EXISTS pg_trgm;
Your connection URL should look like:
bash
<postgresql+asyncpg://prefect_user:strong-password@<postgres-host>:5432/prefect>
Note: use postgresql+asyncpg://..., not plain postgresql://....
---
3. Stop using the ephemeral profile
You should create or switch to a normal profile.
First, see your profiles:
bash
prefect profile ls
Then create/use a production one:
bash
prefect profile use default
Or create a dedicated one by setting config into a new profile if you prefer.
If default doesn’t exist or you want a dedicated name, you can just use config with that profile active afterward.
---
4. Set production config
Set your API URL and DB connection under the non-ephemeral profile.
Example:
bash
prefect config set PREFECT_API_URL="<http://192.168.29.151:4200/api>"
prefect config set PREFECT_API_DATABASE_CONNECTION_URL="<postgresql+asyncpg://prefect_user:strong-password@127.0.0.1:5432/prefect>"
prefect config set PREFECT_API_DATABASE_MIGRATE_ON_START="false"
Then inspect:
bash
prefect config view
You want to not see:
bash
PREFECT_PROFILE='ephemeral'
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true'
If those are still present in the active profile, remove or override them.
---
5. Initialize the PostgreSQL schema
Before starting the server in production, run migrations manually:
bash
prefect server database upgrade -y
This creates/upgrades the schema in PostgreSQL.
Then start the server:
bash
prefect server start --host 0.0.0.0 --port 4200
Health check:
bash
curl <http://192.168.29.151:4200/api/health>
---
6. Minimal production env example
If you want to run this from shell/systemd/docker, these are the key env vars:
bash
export PREFECT_API_URL="<http://192.168.29.151:4200/api>"
export PREFECT_API_DATABASE_CONNECTION_URL="<postgresql+asyncpg://prefect_user:strong-password@127.0.0.1:5432/prefect>"
export PREFECT_API_DATABASE_MIGRATE_ON_START="false"
Then:
bash
prefect server database upgrade -y
prefect server start --host 0.0.0.0 --port 4200
---
7. About migrating existing SQLite data
This is the tricky part.Marvin
07/08/2026, 6:26 PMprefect server database upgrade -y
6. Start server
7. Re-register/redeploy flows
8. Validate workers and UI
9. Keep old SQLite DB untouched for rollback/reference
---
9. Rollback plan
If something goes wrong, switch back to the old profile or restore the old DB-backed setup:
bash
cp ~/.prefect/prefect.db.backup ~/.prefect/prefect.db
Then restore the prior profile/config and restart your old server.
---
10. Important production note
If you later want multi-server / HA style Prefect Server, PostgreSQL is required, and you’ll also want Redis for coordination/messaging per the self-hosted guidance.
---
If you want, I can give you either:
1. a step-by-step migration checklist for your exact host (/home/prefect, local Postgres), or
2. a systemd service file + environment file for running Prefect Server against PostgreSQL in production.Shubham
07/08/2026, 6:55 PMMarvin
07/08/2026, 6:55 PMMarvin
07/08/2026, 6:55 PMShubham
07/08/2026, 6:57 PMMarvin
07/08/2026, 6:57 PMMarvin
07/08/2026, 6:57 PMbash
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:Network@5714@127.0.0.1:5432/prefect>"
Prefect/asyncpg parses that as part of the hostname, which leads to:
bash
socket.gaierror: [Errno -2] Name or service not known
Fix: URL-encode the @ in the password as %40
So use:
bash
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:Network%405714@127.0.0.1:5432/prefect>"
---
Recommended corrected service
ini
[Unit]
Description=Prefect Server
After=network-online.target postgresql.service
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/home/prefect
Environment="PREFECT_HOME=/home/prefect/.prefect"
Environment="PREFECT_SERVER_API_HOST=192.168.29.151"
Environment="PREFECT_SERVER_API_PORT=4200"
Environment="PREFECT_SERVER_API_KEEPALIVE_TIMEOUT=60"
Environment="PREFECT_SERVER_LOGGING_LEVEL=DEBUG"
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:Network%405714@127.0.0.1:5432/prefect>"
Environment="PREFECT_SERVER_API_AUTH_STRING=astra:xxxxxxx"
Environment="PREFECT_API_DATABASE_MIGRATE_ON_START=true"
ExecStart=/home/prefect/.venv/bin/prefect server start --host 0.0.0.0 --port 4200 --keep-alive-timeout 60
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
---
Then reload and restart systemd
bash
systemctl daemon-reload
systemctl restart prefect-server
systemctl status prefect-server -n 100
journalctl -u prefect-server -n 100 --no-pager
---
Also verify PostgreSQL manually first
Before retrying the service, test the DB:
bash
psql "<postgresql://prefect:Network@5714@127.0.0.1:5432/prefect>"
That will also fail for the same reason unless escaped. Use either:
bash
psql "<postgresql://prefect:Network%405714@127.0.0.1:5432/prefect>"
or simpler interactively:
bash
PGPASSWORD='Network@5714' psql -h 127.0.0.1 -U prefect -d prefect
---
Important note about the deleted .db, -shm, -wal files
That’s fine if you are intentionally moving fully to PostgreSQL and no longer need the old local SQLite state.
---
Two more suggestions
1. Prefer binding the server to 0.0.0.0 only once
You already do this in ExecStart, so PREFECT_SERVER_API_HOST=192.168.29.151 may be unnecessary and could be removed to avoid confusion.
2. Consider disabling auto-migrate after first successful boot
For steady production use:
ini
Environment="PREFECT_API_DATABASE_MIGRATE_ON_START=false"
and run DB upgrades manually when needed.
---
Minimal cleaner version I’d use
ini
[Unit]
Description=Prefect Server
After=network-online.target postgresql.service
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/home/prefect
Environment="PREFECT_HOME=/home/prefect/.prefect"
Environment="PREFECT_SERVER_LOGGING_LEVEL=INFO"
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:Network%405714@127.0.0.1:5432/prefect>"
Environment="PREFECT_SERVER_API_AUTH_STRING=astra:xxxxxxx"
Environment="PREFECT_API_DATABASE_MIGRATE_ON_START=true"
ExecStart=/home/prefect/.venv/bin/prefect server start --host 0.0.0.0 --port 4200 --keep-alive-timeout 60
Restart=on-failure
RestartSec=10
[Install]
WantedBy=multi-user.target
---
If you want, I can give you a fully production-hardened systemd unit with:
- dedicated prefect user
- external env file
- PostgreSQL readiness checks
- log tuning
- safer restart behaviorShubham
07/08/2026, 7:01 PMMarvin
07/08/2026, 7:01 PMMarvin
07/08/2026, 7:01 PM.venv.
It looks like you were on 3.6.15, and the latest release notes tool shows 3.7.7 as current.
Release notes:
- Prefect releases
- Latest compare shown: 3.7.6 → 3.7.7
Recommended upgrade plan
Since this is your server host, do this in order:
1. stop the Prefect service
2. activate the venv
3. upgrade prefect
4. verify the version
5. run DB migrations
6. restart the service
7. verify health
---
1. Stop the service
bash
systemctl stop prefect-server
---
2. Activate your virtualenv
bash
cd /home/prefect
source .venv/bin/activate
Verify current version first:
bash
prefect version
pip show prefect
---
3. Upgrade Prefect
bash
pip install --upgrade prefect
If you want to pin specifically to the latest known version from the release notes:
bash
pip install --upgrade "prefect==3.7.7"
Then verify:
bash
prefect version
---
4. Upgrade the database schema
Because you’re running Prefect Server with PostgreSQL, run migrations before restart:
bash
prefect server database upgrade -y
---
5. Restart the service
bash
systemctl start prefect-server
systemctl status prefect-server -n 100
Check logs:
bash
journalctl -u prefect-server -n 100 --no-pager
---
6. Verify API health
bash
curl <http://192.168.29.151:4200/api/health>
And from the same shell with the venv active:
bash
prefect config view
prefect version
---
Recommended post-upgrade cleanup
If the upgrade and migrations succeed, set this in your systemd env later:
ini
Environment="PREFECT_API_DATABASE_MIGRATE_ON_START=false"
Then future upgrades should use:
bash
systemctl stop prefect-server
source /home/prefect/.venv/bin/activate
pip install --upgrade prefect
prefect server database upgrade -y
systemctl start prefect-server
That’s a cleaner production pattern.
---
If pip install --upgrade prefect fails
Try:
bash
python -m pip install --upgrade pip setuptools wheel
python -m pip install --upgrade prefect
If you installed with extras previously, use the same extras again, for example:
bash
python -m pip install --upgrade "prefect[aws]"
or:
bash
python -m pip install --upgrade "prefect[docker]"
Only do that if you already rely on those integrations.
---
One important note
The tool could not find /home/prefect/.venv/bin/prefect directly, so if that path really exists on your machine, that was just a tool environment limitation here. On your server, your local shell is the source of truth.
---
If you want, I can give you:
- a copy-paste upgrade script, or
- a safer staged upgrade procedure with backup + rollback for your PostgreSQL-backed Prefect server.Shubham
07/08/2026, 7:03 PMMarvin
07/08/2026, 7:03 PMMarvin
07/08/2026, 7:04 PM.venv
Those do not automatically match.
---
Why it still shows ephemeral and sqlite
Your prefect config view shows:
bash
PREFECT_PROFILE='ephemeral'
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true'
That means your CLI is still reading the old profile from:
bash
~/.prefect/profiles.toml or ~/.prefect/profiles.yaml
So when you run:
bash
prefect version
it reports the active CLI profile, not necessarily the actual database used by the systemd service.
Also, this:
bash
Version: 3.6.15
means your .venv still has Prefect 3.6.15 installed. It has not been upgraded yet in that environment.
---
Most likely situation
Your systemd service is running with these environment vars:
ini
Environment="PREFECT_API_DATABASE_CONNECTION_URL=postgresql+asyncpg://..."
so the service is using PostgreSQL.
But your shell session still has:
- old Prefect package version: 3.6.15
- active profile: ephemeral
- old local config pointing at SQLite/ephemeral mode
That’s why the UI starts empty and your CLI still says SQLite/ephemeral.
---
How to confirm what the service is really using
Check the service environment and logs:
bash
systemctl cat prefect-server
journalctl -u prefect-server -n 100 --no-pager
Look for:
- PostgreSQL connection success
- database migrations
- no fallback to SQLite
You can also test the API health:
bash
curl <http://192.168.29.151:4200/api/health>
---
Why the UI is empty
Because you deleted the SQLite DB files and started against a new database.
Since Prefect does not automatically migrate SQLite data into PostgreSQL, your new PostgreSQL-backed server came up with a fresh empty schema. That part is expected.
---
How to fix your CLI/profile so it matches the server
You should stop using the ephemeral profile.
First, list profiles:
bash
prefect profile ls
Then switch away from ephemeral, for example:
bash
prefect profile use default
If needed, set the correct API URL again:
bash
prefect config set PREFECT_API_URL="<http://192.168.29.151:4200/api>"
prefect config set PREFECT_API_AUTH_STRING="astra:xxxxxxx"
Then check:
bash
prefect config view
You should not see:
bash
PREFECT_PROFILE='ephemeral'
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true'
---
If default does not exist or is wrong
You can inspect the profile file:
bash
cat ~/.prefect/profiles.toml
or:
bash
cat ~/.prefect/profiles.yaml
Depending on your install.
If you want a clean reset, I’d suggest:
- keep a backup of the profile file
- create/use a fresh non-ephemeral profile
- set only the needed config
---
How to actually upgrade Prefect in the venv
Right now your venv still says:
bash
Version: 3.6.15
So upgrade it explicitly:
bash
source /home/prefect/.venv/bin/activate
python -m pip install --upgrade pip
python -m pip install --upgrade prefect
prefect version
If you want to pin:
bash
python -m pip install "prefect==3.7.7"
Then run DB migrations:
bash
prefect server database upgrade -y
Then restart service:
bash
systemctl restart prefect-server
---
Important distinction
prefect version output includes this section:
bash
Server:
Database: sqlite
That is based on the current CLI context/config, not proof that your systemd service is actually using SQLite right now.
Your active shell is still pointed at the old profile, so it’s misleading you.
---
What I recommend you do next, exactly
Run these commands and share output if anything looks odd:
```bash
source /home/prefect/.venv/bin/activate
prefect profile ls
prefect config view
python -m pip show prefect
systemctl cat prefect-serverMarvin
07/08/2026, 7:04 PMThen fix the profile:
```bash
prefect profile use default
prefect config set PREFECT_API_URL="<http://192.168.29.151:4200/api>"
prefect config set PREFECT_API_AUTH_STRING="astra:xxxxxxx"
prefect config view
Then upgrade Prefect:
bash
python -m pip install --upgrade prefect
prefect version
---
If you want, I can give you a precise cleanup sequence to:
- remove the ephemeral profile problem
- align CLI with your running server
- upgrade Prefect
- verify PostgreSQL is really in useShubham
07/08/2026, 7:06 PMMarvin
07/08/2026, 7:06 PMMarvin
07/08/2026, 7:06 PMephemeral profile, and that profile is configured for ephemeral/SQLite behavior.
So even if your systemd server process is using PostgreSQL, your interactive prefect CLI still reports:
bash
Profile: ephemeral
Server:
Database: sqlite
because that is the only profile you currently have.
---
What this means
Your command output:
bash
prefect profile ls
shows only:
bash
* ephemeral
So your local CLI config still thinks Prefect is running in ephemeral mode.
That does not necessarily mean the running service is using SQLite. It means your CLI context is.
---
Why this happened
You started Prefect originally in ephemeral mode, and Prefect created only this profile:
bash
ephemeral
Then you changed the systemd service to use PostgreSQL via environment variables.
But that does not rewrite your CLI profile in ~/.prefect.
So now you have:
- systemd service → likely PostgreSQL
- interactive CLI profile → still ephemeral/SQLite
---
How to fix it
You need to create a new non-ephemeral profile or replace the current one.
Since default doesn’t exist, create one.
First check the profile commands available:
bash
prefect profile --help
If create is available, do:
bash
prefect profile create server
prefect profile use server
Then set the real API connection values:
bash
prefect config set PREFECT_API_URL="<http://192.168.29.151:4200/api>"
prefect config set PREFECT_API_AUTH_STRING="astra:xxxxxxx"
Now check:
bash
prefect config view
prefect version
You should no longer see:
bash
Profile: ephemeral
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true'
---
If prefect profile create is not available
Then the easiest fix is to edit the profile config file directly.
Please run:
bash
ls -la ~/.prefect
and then:
bash
cat ~/.prefect/profiles.toml
If that file doesn’t exist, try:
bash
cat ~/.prefect/profiles.yaml
You likely have a file defining only ephemeral.
You can replace it with a non-ephemeral profile.
A typical structure looks like this:
toml
active = "server"
[profiles.server]
PREFECT_API_URL = "<http://192.168.29.151:4200/api>"
PREFECT_API_AUTH_STRING = "astra:xxxxxxx"
After saving, reopen shell or run:
bash
prefect config view
prefect profile ls
prefect version
---
Important clarification about prefect version
This part:
bash
Server:
Database: sqlite
reflects the current client/profile settings, not a guaranteed statement about what your systemd service is using at runtime.
Because your active profile is ephemeral, Prefect infers SQLite there.
---
How to verify the actual running server is on PostgreSQL
Use the service logs:
bash
journalctl -u prefect-server -n 100 --no-pager
You want to see successful startup with no SQLite path usage and no DB connection errors.
Also verify PostgreSQL really has Prefect tables:
bash
psql -h 127.0.0.1 -U prefect -d prefect -c "\dt"
If you see lots of Prefect tables, the server DB is PostgreSQL.
---
Best practical fix for you right now
Since only ephemeral exists, I recommend:
1. back up your profile file
2. create a new server profile
3. make it active
4. set only:
- PREFECT_API_URL
- PREFECT_API_AUTH_STRING
Do not keep PREFECT_SERVER_ALLOW_EPHEMERAL_MODE=true in the active client profile.
---
If you want, I can help you do this exactly from your current machine — just paste the output of:
bash
prefect profile --help
ls -la ~/.prefect
cat ~/.prefect/profiles.toml
or if no toml file exists:
bash
cat ~/.prefect/profiles.yamlShubham
07/08/2026, 7:10 PMMarvin
07/08/2026, 7:10 PMMarvin
07/08/2026, 7:10 PMini
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:Network%405714@127.0.0.1:5432/prefect>"
Those < > characters should not be there.
Because of that, Prefect is not getting a valid DB URL, and it’s likely falling back to SQLite behavior.
Use this instead:
ini
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:Network%405714@127.0.0.1:5432/prefect>"
No angle brackets.
---
Why prefect version still says SQLite
Your CLI is connected to the server at:
bash
PREFECT_API_URL=<http://192.168.29.151:4200/api>
but the Server: section in prefect version is based on local settings/runtime inference and can be misleading here.
The real issue is that your systemd service likely never got a valid PostgreSQL URL because of the malformed environment variable.
---
Fix your service file to this
ini
[Unit]
Description=Prefect Server
After=network-online.target postgresql.service
Wants=network-online.target
[Service]
Type=simple
User=root
WorkingDirectory=/home/prefect
Environment="PREFECT_HOME=/home/prefect/.prefect"
Environment="PREFECT_SERVER_API_HOST=192.168.29.151"
Environment="PREFECT_SERVER_API_PORT=4200"
Environment="PREFECT_SERVER_API_KEEPALIVE_TIMEOUT=60"
Environment="PREFECT_SERVER_LOGGING_LEVEL=DEBUG"
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:Network%405714@127.0.0.1:5432/prefect>"
Environment="PREFECT_SERVER_API_AUTH_STRING=astra:Network@5714"
ExecStart=/home/prefect/.venv/bin/prefect server start --host 0.0.0.0 --port 4200 --keep-alive-timeout 60
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target
---
Then reload and restart
bash
systemctl daemon-reload
systemctl restart prefect-server
systemctl status prefect-server -n 100
journalctl -u prefect-server -n 100 --no-pager
---
Then verify PostgreSQL directly
Run:
bash
PGPASSWORD='Network@5714' psql -h 127.0.0.1 -U prefect -d prefect -c "\dt"
If Prefect initialized correctly, you should see many tables.
You can also test whether the server created schema:
bash
PGPASSWORD='Network@5714' psql -h 127.0.0.1 -U prefect -d prefect -c "select * from alembic_version;"
---
Strong recommendation
For production, add this too after first successful startup/migration:
ini
Environment="PREFECT_API_DATABASE_MIGRATE_ON_START=false"
Then handle upgrades with:
bash
source /home/prefect/.venv/bin/activate
prefect server database upgrade -y
systemctl restart prefect-server
---
Also note
This line is okay as a credential value:
ini
Environment="PREFECT_SERVER_API_AUTH_STRING=astra:Network@5714"
because systemd passes it as a plain string; it is not a URL.
Only the PostgreSQL URL needed %40 encoding.
---
If you want, I can give you a final corrected production-ready unit file plus a separate /etc/default/prefect-server env file so you don’t keep secrets inline in the unit.Nate
07/08/2026, 7:14 PM