<@ULVA73B9P> help me migrate this prefect sqlite deployment to postgresql based production style (.v...
s
@Marvin help me migrate this prefect sqlite deployment to postgresql based production style (.venv) root@Prefect:/home/prefect# prefect --version 3.6.15 (.venv) root@Prefect:/home/prefect# prefect config view 🚀 you are connected to: 192.168.29.151 PREFECT_PROFILE='ephemeral' PREFECT_API_AUTH_STRING='********' (from profile) PREFECT_API_URL='192.168.29.151/api' (from profile) PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true' (from profile) PREFECT_SERVER_API_AUTH_STRING='********' (from profile) (.venv) root@Prefect:/home/prefect#
m
thought for 243.2 seconds
You’re currently running Prefect Server in an ephemeral/dev-style profile:
Copy code
bash
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:
Copy code
bash
~/.prefect/prefect.db
Back it up first:
Copy code
bash
cp ~/.prefect/prefect.db ~/.prefect/prefect.db.backup
If you want an extra export:
Copy code
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:
Copy code
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:
Copy code
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:
Copy code
bash
prefect profile ls
Then create/use a production one:
Copy code
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:
Copy code
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:
Copy code
bash
prefect config view
You want to not see:
Copy code
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:
Copy code
bash
prefect server database upgrade -y
This creates/upgrades the schema in PostgreSQL. Then start the server:
Copy code
bash
prefect server start --host 0.0.0.0 --port 4200
Health check:
Copy code
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:
Copy code
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:
Copy code
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.
Officially, Prefect does not document or support a one-command SQLite→PostgreSQL migration path. So you have 2 realistic options: Option A — recommended: start fresh on PostgreSQL - keep the SQLite backup for historical reference - redeploy flows - let new runs/events accumulate in PostgreSQL Option B — custom/manual migration - possible, but not officially supported - you would need to export/import data yourself and carefully validate constraints/types - this carries risk, especially around: - UUID fields - JSON columns - foreign keys - Alembic migration state If history retention is critical, I can help you design a cautious migration workflow, but I would not recommend direct table copy as a first move for production. --- 8. Suggested cutover plan Safest approach: 1. Back up SQLite 2. Stand up PostgreSQL 3. Create a new non-ephemeral Prefect profile 4. Point Prefect to PostgreSQL 5.
prefect 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:
Copy code
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.
s
@Marvin i deleted .db and two more shm and wal file from prefect folder and created service [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@5714@127.0.0.1:5432/prefect" Environment="PREFECT_SERVER_API_AUTH_STRING=astra:xxxxxxx" 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 now service is restarting (.venv) root@Prefect:/home/prefect# journalctl -u prefect-server -n 50 --no-pager Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/sqlalchemy/engine/default.py", line 630, in connect Jul 08 185516 Prefect prefect[2879861]: return self.loaded_dbapi.connect(*cargs, **cparams) # type: ignore[no-any-return] # NOQA: E501 Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/sqlalchemy/dialects/postgresql/asyncpg.py", line 955, in connect Jul 08 185516 Prefect prefect[2879861]: await_only(creator_fn(*arg, **kw)), Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only Jul 08 185516 Prefect prefect[2879861]: return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501 Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn Jul 08 185516 Prefect prefect[2879861]: value = await result Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/asyncpg/connection.py", line 2443, in connect Jul 08 185516 Prefect prefect[2879861]: return await connect_utils._connect( Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 1249, in _connect Jul 08 185516 Prefect prefect[2879861]: raise last_error or exceptions.TargetServerAttributeNotMatched( Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 1218, in _connect Jul 08 185516 Prefect prefect[2879861]: conn = await _connect_addr( Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 1054, in _connect_addr Jul 08 185516 Prefect prefect[2879861]: return await __connect_addr(params, True, *args) Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 1099, in __connect_addr Jul 08 185516 Prefect prefect[2879861]: tr, pr = await connector Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/home/prefect/.venv/lib/python3.12/site-packages/asyncpg/connect_utils.py", line 969, in _create_ssl_connection Jul 08 185516 Prefect prefect[2879861]: tr, pr = await loop.create_connection( Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/usr/lib/python3.12/asyncio/base_events.py", line 1080, in create_connection Jul 08 185516 Prefect prefect[2879861]: infos = await self._ensure_resolved( Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/usr/lib/python3.12/asyncio/base_events.py", line 1456, in _ensure_resolved Jul 08 185516 Prefect prefect[2879861]: return await loop.getaddrinfo(host, port, family=family, type=type, Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/usr/lib/python3.12/asyncio/base_events.py", line 901, in getaddrinfo Jul 08 185516 Prefect prefect[2879861]: return await self.run_in_executor( Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/usr/lib/python3.12/concurrent/futures/thread.py", line 58, in run Jul 08 185516 Prefect prefect[2879861]: result = self.fn(*self.args, **self.kwargs) Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: File "/usr/lib/python3.12/socket.py", line 963, in getaddrinfo Jul 08 185516 Prefect prefect[2879861]: for res in _socket.getaddrinfo(host, port, family, type, proto, flags): Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: socket.gaierror: [Errno -2] Name or service not known Jul 08 185516 Prefect prefect[2879861]: ERROR: Application startup failed. Exiting. Jul 08 185516 Prefect prefect[2879861]: Server stopped! Jul 08 185517 Prefect systemd[1]: prefect-server.service: Main process exited, code=exited, status=3/NOTIMPLEMENTED Jul 08 185517 Prefect systemd[1]: prefect-server.service: Failed with result 'exit-code'. Jul 08 185517 Prefect systemd[1]: prefect-server.service: Consumed 7.842s CPU time. (.venv) root@Prefect:/home/prefect#
m
Your message was too long, here's your message at the allowed limit: i deleted db and two more shm and wal file from prefect folder and created service [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@5714>@127 0 0 1 5432/prefect Environment= PREFECT_SERVER_API_AUTH_STRING=astra xxxxxxx 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 now service is restarting ( venv) root@Prefect /home/prefect# journalctl -u prefect-server -n 50 --no-pager Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/sqlalchemy/engine/default py line 630 in connect Jul 08 18 55 16 Prefect prefect[2879861] return self loaded_dbapi connect(*cargs *cparams) # type ignore[no-any-return] # NOQA E501 Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/sqlalchemy/dialects/postgresql/asyncpg py line 955 in connect Jul 08 18 55 16 Prefect prefect[2879861] await_only(creator_fn(*arg *kw)) Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/sqlalchemy/util/_concurrency_py3k py line 132 in await_only Jul 08 18 55 16 Prefect prefect[2879861] return current parent switch(awaitable) # type ignore[no-any-return attr-defined] # noqa E501 Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/sqlalchemy/util/_concurrency_py3k py line 196 in greenlet_spawn Jul 08 18 55 16 Prefect prefect[2879861] value = await result Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/asyncpg/connection py line 2443 in connect Jul 08 18 55 16 Prefect prefect[2879861] return await connect_utils _connect( Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/asyncpg/connect_utils py line 1249 in _connect Jul 08 18 55 16 Prefect prefect[2879861] raise last_error or exceptions TargetServerAttributeNotMatched( Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/asyncpg/connect_utils py line 1218 in _connect Jul 08 18 55 16 Prefect prefect[2879861] conn = await _connect_addr( Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/asyncpg/connect_utils py line 1054 in _connect_addr Jul 08 18 55 16 Prefect prefect[2879861] return await __connect_addr(params True *args) Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/asyncpg/connect_utils py line 1099 in __connect_addr Jul 08 18 55 16 Prefect prefect[2879861] tr pr = await connector Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /home/prefect/ venv/lib/python3 12/site-packages/asyncpg/connect_utils py line 969 in _create_ssl_connection Jul 08 18 55 16 Prefect prefect[2879861] tr pr = await loop create_conn
ection( Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /usr/lib/python3 12/asyncio/base_events py line 1080 in create_connection Jul 08 18 55 16 Prefect prefect[2879861] infos = await self _ensure_resolved( Jul 08 18 55 16 Prefect prefect[2879861] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 18 55 16 Prefect prefect[2879861] File /usr/lib/python3 12/asyncio/base_events py line 1456 in _ensure_resolved Jul 08 18
s
@Marvin i deleted .db and two more shm and wal file from prefect folder and created service [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@5714@127.0.0.1:5432/prefect" Environment="PREFECT_SERVER_API_AUTH_STRING=astra:xxxxxxx" 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 now service is restarting /usr/lib/python3.12/socket.py", line 963, in getaddrinfo Jul 08 185516 Prefect prefect[2879861]: for res in _socket.getaddrinfo(host, port, family, type, proto, flags): Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: socket.gaierror: [Errno -2] Name or service not known Jul 08 185516 Prefect prefect[2879861]: ERROR: Application startup failed. Exiting. Jul 08 185516 Prefect prefect[2879861]: Server stopped! Jul 08 185517 Prefect systemd[1]: prefect-server.service: Main process exited, code=exited, status=3/NOTIMPLEMENTED Jul 08 185517 Prefect systemd[1]: prefect-server.service: Failed with result 'exit-code'. Jul 08 185517 Prefect systemd[1]: prefect-server.service: Consumed 7.842s CPU time. (.venv) root@Prefect:/home/prefect#/usr/lib/python3.12/socket.py", line 963, in getaddrinfo Jul 08 185516 Prefect prefect[2879861]: for res in _socket.getaddrinfo(host, port, family, type, proto, flags): Jul 08 185516 Prefect prefect[2879861]: ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Jul 08 185516 Prefect prefect[2879861]: socket.gaierror: [Errno -2] Name or service not known Jul 08 185516 Prefect prefect[2879861]: ERROR: Application startup failed. Exiting. Jul 08 185516 Prefect prefect[2879861]: Server stopped! Jul 08 185517 Prefect systemd[1]: prefect-server.service: Main process exited, code=exited, status=3/NOTIMPLEMENTED Jul 08 185517 Prefect systemd[1]: prefect-server.service: Failed with result 'exit-code'. Jul 08 185517 Prefect systemd[1]: prefect-server.service: Consumed 7.842s CPU time. (.venv) root@Prefect:/home/prefect#
m
thought for 12.8 seconds
The restart loop is very likely caused by your PostgreSQL connection URL, not the deleted SQLite files. This line is malformed because your password contains `@`:
Copy code
bash
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:
Copy code
bash
socket.gaierror: [Errno -2] Name or service not known
Fix: URL-encode the
@
in the password as
%40
So use:
Copy code
bash
Environment="PREFECT_API_DATABASE_CONNECTION_URL=<postgresql+asyncpg://prefect:Network%405714@127.0.0.1:5432/prefect>"
--- Recommended corrected service
Copy code
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
Copy code
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:
Copy code
bash
psql "<postgresql://prefect:Network@5714@127.0.0.1:5432/prefect>"
That will also fail for the same reason unless escaped. Use either:
Copy code
bash
psql "<postgresql://prefect:Network%405714@127.0.0.1:5432/prefect>"
or simpler interactively:
Copy code
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:
Copy code
ini
Environment="PREFECT_API_DATABASE_MIGRATE_ON_START=false"
and run DB upgrades manually when needed. --- Minimal cleaner version I’d use
Copy code
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 behavior
s
@Marvin now help me to upgrade prefect to latest version
m
thought for 11.7 seconds
Yes — here’s the safest way to upgrade your Prefect install in that
.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
Copy code
bash
systemctl stop prefect-server
--- 2. Activate your virtualenv
Copy code
bash
cd /home/prefect
source .venv/bin/activate
Verify current version first:
Copy code
bash
prefect version
pip show prefect
--- 3. Upgrade Prefect
Copy code
bash
pip install --upgrade prefect
If you want to pin specifically to the latest known version from the release notes:
Copy code
bash
pip install --upgrade "prefect==3.7.7"
Then verify:
Copy code
bash
prefect version
--- 4. Upgrade the database schema Because you’re running Prefect Server with PostgreSQL, run migrations before restart:
Copy code
bash
prefect server database upgrade -y
--- 5. Restart the service
Copy code
bash
systemctl start prefect-server
systemctl status prefect-server -n 100
Check logs:
Copy code
bash
journalctl -u prefect-server -n 100 --no-pager
--- 6. Verify API health
Copy code
bash
curl <http://192.168.29.151:4200/api/health>
And from the same shell with the venv active:
Copy code
bash
prefect config view
prefect version
--- Recommended post-upgrade cleanup If the upgrade and migrations succeed, set this in your systemd env later:
Copy code
ini
Environment="PREFECT_API_DATABASE_MIGRATE_ON_START=false"
Then future upgrades should use:
Copy code
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:
Copy code
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:
Copy code
bash
python -m pip install --upgrade "prefect[aws]"
or:
Copy code
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.
s
@Marvin after service restart i can see the prefect with emtpy start but root@Prefect:/home/prefect# source .venv/bin/activate (.venv) root@Prefect:/home/prefect# prefect config view 🚀 you are connected to: 192.168.29.151 PREFECT_PROFILE='ephemeral' PREFECT_API_AUTH_STRING='********' (from profile) PREFECT_API_URL='192.168.29.151/api' (from profile) PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true' (from profile) PREFECT_SERVER_API_AUTH_STRING='********' (from profile) (.venv) root@Prefect:/home/prefect# ^C (.venv) root@Prefect:/home/prefect# prefect version Version: 3.6.15 API version: 0.8.4 Python version: 3.12.3 Git commit: 757a089b Built: Fri, Jan 30, 2026 12:27 AM OS/Arch: linux/x86_64 Profile: ephemeral Server type: server Pydantic version: 2.12.5 Server: Database: sqlite SQLite version: 3.45.1 Integrations: prefect-docker: 0.7.1 (.venv) root@Prefect:/home/prefect# why this showing old ?
m
thought for 35.5 seconds
Because your CLI shell is still using the old local profile config, and likely the old package too. You actually have two separate things here: 1. The running server service 2. Your interactive CLI environment in
.venv
Those do not automatically match. --- Why it still shows
ephemeral
and
sqlite
Your
prefect config view
shows:
Copy code
bash
PREFECT_PROFILE='ephemeral'
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true'
That means your CLI is still reading the old profile from:
Copy code
bash
~/.prefect/profiles.toml or ~/.prefect/profiles.yaml
So when you run:
Copy code
bash
prefect version
it reports the active CLI profile, not necessarily the actual database used by the systemd service. Also, this:
Copy code
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:
Copy code
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:
Copy code
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:
Copy code
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:
Copy code
bash
prefect profile ls
Then switch away from ephemeral, for example:
Copy code
bash
prefect profile use default
If needed, set the correct API URL again:
Copy code
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:
Copy code
bash
prefect config view
You should not see:
Copy code
bash
PREFECT_PROFILE='ephemeral'
PREFECT_SERVER_ALLOW_EPHEMERAL_MODE='true'
--- If
default
does not exist or is wrong
You can inspect the profile file:
Copy code
bash
cat ~/.prefect/profiles.toml
or:
Copy code
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:
Copy code
bash
Version: 3.6.15
So upgrade it explicitly:
Copy code
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:
Copy code
bash
python -m pip install "prefect==3.7.7"
Then run DB migrations:
Copy code
bash
prefect server database upgrade -y
Then restart service:
Copy code
bash
systemctl restart prefect-server
--- Important distinction
prefect version
output includes this section:
Copy code
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-server
journalctl -u prefect-server -n 80 --no-pager
Copy code
Then 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:
Copy code
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 use
s
@Marvin i haven't upgraded yet im asking about i migrated to postgresql from sqlite but still (.venv) root@Prefect:/home/prefect# prefect version Version: 3.6.15 API version: 0.8.4 Python version: 3.12.3 Git commit: 757a089b Built: Fri, Jan 30, 2026 12:27 AM OS/Arch: linux/x86_64 Profile: ephemeral Server type: server Pydantic version: 2.12.5 Server: Database: sqlite SQLite version: 3.45.1 Integrations: prefect-docker: 0.7.1 (.venv) root@Prefect:/home/prefect# prefect profile ls ┏━━━━━━━━━━━━━━━━━━━━━┓ ┃ Available Profiles: ┃ ┡━━━━━━━━━━━━━━━━━━━━━┩ │ * ephemeral │ └─────────────────────┘ * active profile (.venv) root@Prefect:/home/prefect# prefect profile use default Profile 'default' not found. (.venv) root@Prefect:/home/prefect#
m
thought for 10.0 seconds
Got it — you have not upgraded yet. The issue is not version-related. What you're seeing is because your CLI is still using the
ephemeral
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:
Copy code
bash
Profile: ephemeral
Server:
  Database: sqlite
because that is the only profile you currently have. --- What this means Your command output:
Copy code
bash
prefect profile ls
shows only:
Copy code
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:
Copy code
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:
Copy code
bash
prefect profile --help
If create is available, do:
Copy code
bash
prefect profile create server
prefect profile use server
Then set the real API connection values:
Copy code
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:
Copy code
bash
prefect config view
prefect version
You should no longer see:
Copy code
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:
Copy code
bash
ls -la ~/.prefect
and then:
Copy code
bash
cat ~/.prefect/profiles.toml
If that file doesn’t exist, try:
Copy code
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:
Copy code
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:
Copy code
bash
prefect config view
prefect profile ls
prefect version
--- Important clarification about
prefect version
This part:
Copy code
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:
Copy code
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:
Copy code
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:
Copy code
bash
prefect profile --help
ls -la ~/.prefect
cat ~/.prefect/profiles.toml
or if no toml file exists:
Copy code
bash
cat ~/.prefect/profiles.yaml
s
@Marvin (.venv) root@Prefect:/home/prefect# prefect config view prefect version 🚀 you are connected to: 192.168.29.151 PREFECT_PROFILE='server' PREFECT_API_AUTH_STRING='********' (from profile) PREFECT_API_URL='192.168.29.151/api' (from profile) Version: 3.6.15 API version: 0.8.4 Python version: 3.12.3 Git commit: 757a089b Built: Fri, Jan 30, 2026 12:27 AM OS/Arch: linux/x86_64 Profile: server Server type: server Pydantic version: 2.12.5 Server: Database: sqlite SQLite version: 3.45.1 Integrations: prefect-docker: 0.7.1 (.venv) root@Prefect:/home/prefect# my service config [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
m
thought for 8.6 seconds
The problem is in this line of your service file:
Copy code
ini
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:
Copy code
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:
Copy code
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
Copy code
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
Copy code
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:
Copy code
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:
Copy code
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:
Copy code
ini
Environment="PREFECT_API_DATABASE_MIGRATE_ON_START=false"
Then handle upgrades with:
Copy code
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:
Copy code
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.
n
hi @Shubham - have you considered using the prefect MCP with an agent like claude code?