Migrating Tier 1 → Tier 2
The migration is two env-var changes and a compose-file edit. No data migration, no downtime if you do it right.
Pre-migration checklist
Section titled “Pre-migration checklist”- You have an issued
SCANI_CLOUD_URLandSCANI_CLOUD_API_KEYfrom the data-provider operator. - You have a recent Postgres backup (this should be true regardless; see Backup & restore).
- You’ve noted which provider keys you currently have set
(
COINGECKO_API_KEY,OPENAI_API_KEY, etc.). These stay. They are read by your api and worker on every tier, not by the data-provider — see You still need your provider API keys.
The migration
Section titled “The migration”-
Edit
.env:SCANI_CLOUD_URL=http://data-provider:8082SCANI_CLOUD_API_KEY=dev_data_provider_key_change_me_not_prod_safeSCANI_CLOUD_URL=https://data-provider.your-host.example.comSCANI_CLOUD_API_KEY=<issued key> -
Edit
docker-compose.prod.yml: comment out thedata-providerservice and removedata-providerfrom thedepends_onofapiandworker(see Pointing api + worker at a hosted endpoint). -
Recreate api + worker. The data-provider container stops automatically when you
docker compose up -dagainst a compose file that no longer defines it.Terminal window docker compose -f docker-compose.prod.yml up -d -
Watch the logs:
Terminal window docker compose -f docker-compose.prod.yml logs -f api workerThe api and worker each log a
scaniCloudUrlfield on boot — there is notierfield. Confirm it reads your hosted endpoint and not(local fallback):Terminal window docker compose -f docker-compose.prod.yml logs api worker \| grep -E '"scaniCloudUrl"'While you are in the logs, check the provider-credentials line too (see Do not remove your provider API keys) — it should read the same before and after the migration.
-
Verify with a synthetic call:
- Open the SPA, navigate to the dashboard, check that prices are fresh.
- Trigger a manual sync on one integration.
- Trigger a screenshot import (if you use it).
What you didn’t have to do
Section titled “What you didn’t have to do”- No data migration. All your data is in your Postgres. It stays. Sync history, transaction ledger, observations, vaults — all intact.
- No re-authentication for users. Sessions live in your Postgres; the tier change is invisible to users.
- No re-encryption of integration credentials. They stay
encrypted with your
ENCRYPTION_KEYon your machine.
Rolling back
Section titled “Rolling back”If something is wrong with the hosted endpoint and you need to fall back:
-
Revert the
.envchange:SCANI_CLOUD_URL=http://data-provider:8082SCANI_CLOUD_API_KEY=<your local key>DATA_PROVIDER_API_KEY=<same as above> -
Uncomment the
data-providerservice indocker-compose.prod.yml. -
docker compose -f docker-compose.prod.yml up -d.
Your provider keys never left, so pricing, AI and chain syncs are unaffected by the round trip in either direction — they were never routed through the data-provider at all.
Email, OG-metadata fetching and token search fall straight back to
their local implementations as soon as SCANI_CLOUD_URL points at
your own container again.
After the migration settles
Section titled “After the migration settles”Once you’re confident in the hosted endpoint:
- Permanently remove the
data-providerservice block from your compose file. - Remove
DATA_PROVIDER_API_KEYand theS3_*block from your.env— the first was only ever the bearer your own container validated, and object storage is now the operator’s bucket.
Do not remove your provider API keys
Section titled “Do not remove your provider API keys”What actually moves
Section titled “What actually moves”Four things, and only four — they are the only adapters
packages/clients/cloud-client/src/ has:
So SMTP_URL, FASTMAIL_API_TOKEN and S3_* can come out of your
.env — magic-link emails go through the operator’s transport and
uploads land in their bucket. The provider API keys cannot.