---
title: "Moving a Live Web Application Off Metered Cloud Platforms (Netlify & Supabase) to a Flat-Rate Docker & PostgreSQL Stack | GreenTree Field Notes"
url: https://www.greentreehosting.com/field-notes/migrating-off-metered-netlify-and-supabase-to-flat-rate-docker-and-postgresql/
description: "By Gene Salvatore: A 7-step sysadmin runbook for graduating a production React + PostgreSQL web application off per-deploy credit meters and non-pausing hourly database compute onto a flat-rate Ubuntu 24.04 LTS Docker + Express + PostgreSQL 16 stack."
format: text/markdown
generated_from: prerendered HTML (build time)
---

[ALL SYSADMIN FIELD NOTES & RUNBOOKS](https://www.greentreehosting.com/field-notes)

FN-2026-08 // CLOUD CONSOLIDATIONServer Transfers & Cutovers · 9 min read

# Moving Off Usage-Metered Cloud (Netlify Credits & Non-Pausing Supabase Compute): Our Production Cutover Runbook to Flat-Rate Docker & PostgreSQL 16

Usage-billed frontend hosts charge credits for every production deploy, and managed cloud databases run an hourly compute meter on every project. Here is the exact step-by-step runbook we use to move a React/TypeScript + Supabase application onto a predictable flat-rate Docker + PostgreSQL 16 server.

Published: 2026-10-25•Last tested: 2026-10-25•Tested migrating Vite + React 19 + Supabase PostgreSQL 15/16 apps to Docker Engine 27.x + Node.js 22 LTS + PostgreSQL 16 on Ubuntu 24.04 LTS

01 // THE SYMPTOM

Frequent content updates burn through monthly deploy credit allowances (15 credits per production deploy on Netlify), and running multiple small client databases adds $10–$25+/mo per database in non-pausing hourly compute fees.

02 // THE ROOT CAUSE

Splitting a standard business web application across usage-metered edge build pipelines and per-project hourly database instances instead of running a consolidated Linux + Docker + PostgreSQL server.

03 // THE PERMANENT FIX

Export the Supabase PostgreSQL schema and data via pg_dump, replace client-side VITE_SUPABASE_ANON_KEY calls with server-side Express + pg pool endpoints, translate netlify.toml redirects/headers into server.mjs, and deploy inside an isolated Docker container.

DEPLOY METER

$0 Per Deploy

Ship photo swaps, copy edits & new prerendered pages without a 15-credit production deploy charge

DATABASE ENGINE

PostgreSQL 16

Standard pg_dump / psql compatibility makes moving from Supabase to dedicated PG16 straightforward

API ARCHITECTURE

Server-Side pg

Replaces browser-exposed anon keys with confined Express endpoints & 7-layer form protection

PREDICTABLE BILLING

$99 / $199 Flat

Flat monthly hosting with active resource monitoring (disproportionate resource use upgrades cleanly)

**Sysadmin Safety Notice:**Test your exported database schema, Express redirect rules, and server-side API routes in a staging container first before pausing or deleting your old Netlify site or Supabase project.

INTERACTIVE SYSADMIN RUNBOOK · SAVED IN YOUR BROWSER

## Interactive Netlify + Supabase to Docker + PostgreSQL Migration Checklist

Check off each step when consolidating a metered frontend + database project onto a flat-rate Linux container:

PROGRESS: 0 OF 6 STEPS VERIFIED (0%)CLICK ANY STEP TO CHECK OFF

1. Export the public schema and data from Supabase using pg_dump --schema=public --no-owner --no-acl

Exporting only the public schema (or specific application tables) avoids importing Supabase-internal auth/storage extension schemas when you only need your application tables.

2. Replace client-side @supabase/supabase-js browser calls with server-side /api/* endpoints

Instead of exposing database credentials or anon keys in VITE_ browser variables, connect to PostgreSQL 16 from your Node/Express server using a server-side pg.Pool.

3. Convert netlify.toml [[redirects]] and [[headers]] into your Express server.mjs

Ensure every legacy 301 redirect and security header (HSTS, X-Frame-Options, nosniff, CSP) is enforced directly by the container HTTP server.

4. Add build-time static HTML prerendering (scripts/prerender.mjs) into the Docker build

Compile both the client bundle and SSR entry during docker build so every route is served as instant, pre-rendered HTML from /app/dist.

5. Verify all routes, 301 redirects, and form submissions against the staging container before switching DNS

Use curl --resolve to test homepage, inner routes, legacy 301 URLs, and live PostgreSQL form inserts before updating the domain’s A record.

6. Keep the old Netlify/Supabase project in read-only standby for 7 days after DNS cutover

Verify zero residual traffic and confirm nightly off-node backups are running on the new server before decommissioning the old metered accounts.

FIELD NOTE 01 // WHY CONSOLIDATING SIMPLIFIES BOTH COST AND SECURITY

## 1. Moving Database Queries From the Browser Back to the Server Where They Belong

When an application is built on a serverless frontend host paired with a hosted backend-as-a-service database, the browser typically talks directly to the database REST API using a public `VITE_SUPABASE_ANON_KEY`. That means your security depends entirely on getting every single PostgreSQL Row-Level Security (`RLS`) policy right—and every production deploy or database hour ticks a usage meter.

When we migrate a site onto our Ubuntu 24.04 LTS Docker + PostgreSQL 16 platform, we simplify both the billing model and the security boundary at the same time:

• **1. No Browser-Exposed Database Keys:** The React frontend no longer talks directly to a public database API. Instead, forms and portal actions send standard `POST /api/...` requests to the local Node.js/Express server inside the container, which validates the input, checks our 7-layer spam shield, and writes to PostgreSQL over the private internal network. • **2. Preserving Every `netlify.toml` 301 Redirect:** One detail people often forget when leaving Netlify is that `netlify.toml` redirects don’t run automatically inside a standard Node or Nginx container. We parse or port every `[[redirects]]` rule directly into `server.mjs` so not a single legacy backlink or bookmarked URL breaks during the move.

| Architecture Layer | Metered Netlify + Supabase Setup | Consolidated GreenTree Docker + PG16 Stack |
| --- | --- | --- |
| Production Deploys | 15 credits per production deploy on credit-based plans | Unlimited deploys included on your flat monthly hosting plan |
| Database Compute Clock | Hourly compute billed 24/7 per active paid database instance | Dedicated PostgreSQL 16 database included on the server |
| Database Access Boundary | Public REST endpoint + VITE_ anon key in browser JS | Private server-side pg.Pool (port 5432 never exposed to public) |
| 301 Redirects & Headers | Configured in proprietary netlify.toml syntax | Enforced natively in Express server.mjs + reverse proxy |

FIELD NOTE 02 // THE PG_DUMP & DOCKER CUTOVER COMMANDS

## 2. Exporting Clean Public Tables From Supabase Into Standard PostgreSQL 16

Because Supabase is built on PostgreSQL, your application data is never trapped—you just need to export it cleanly. If you run a naive full-cluster `pg_dump` against a Supabase connection string, the dump will include Supabase-specific schemas (`auth`, `storage`, `realtime`, `supabase_functions`) and role ownership statements that will throw errors when restored onto a standard self-hosted PostgreSQL 16 server.

The secret to a clean migration is passing `--schema=public --no-owner --no-acl` to `pg_dump`. That exports only your application’s public tables, indexes, sequences, and rows as portable SQL that imports cleanly into any standard PostgreSQL 16 database in seconds.

Exporting Public Schema From Supabase and Importing Into Dedicated PostgreSQL 16

```
# 1. Export only the public application schema & data (stripping cloud-specific role ownership)
pg_dump "postgresql://postgres.<project-ref>:<password>@aws-0-us-east-1.pooler.supabase.com:5432/postgres" \
  --schema=public \
  --no-owner \
  --no-acl \
  --format=custom \
  --file=app_public_migration.dump

# 2. Create the dedicated single-tenant database and role on your target PostgreSQL 16 server
psql -U postgres -c "CREATE ROLE app_user WITH LOGIN PASSWORD 'strong_random_password';"
psql -U postgres -c "CREATE DATABASE app_prod OWNER app_user;"

# 3. Restore cleanly into the new PostgreSQL 16 database and verify row counts
pg_restore --no-owner --no-acl --role=app_user -d app_prod app_public_migration.dump
psql -U app_user -d app_prod -c "SELECT schemaname, relname, n_live_tup FROM pg_stat_user_tables ORDER BY n_live_tup DESC;"
```

⚠ Test on a non-production system first and verify backups before running administrative commands.

SYSADMIN Q&A

## Common Questions on Migrating Off Metered Netlify & Supabase to Flat-Rate Docker

### Can I still use Git-push deployments after moving off Netlify to your Docker cloud?

Yes. Every application container on our platform is wired to a Git webhook build pipeline: when we push a commit to main, the server builds the TypeScript/React bundle, prerenders all static HTML routes, runs our 8-point security check, and swaps the container with zero per-deploy credit fees.

### What if my app grows and starts using heavy CPU, RAM, or database resources?

Our $99/mo and $199/mo plans are flat-rate—meaning we never send surprise usage overage invoices—and they are sized for normal commercial websites and business applications. We actively monitor CPU, memory, disk, database load, and bandwidth across every container so no single $99/mo account can consume all the server’s resources, and if a site grows to use a disproportionate share, we work directly with you to upgrade to a $299+/mo Dedicated Environment or $599+/mo Cluster.

### Why do you pass --no-owner and --no-acl when running pg_dump from Supabase?

Supabase attaches internal roles (such as supabase_admin, anon, authenticated, and service_role) to database objects. When moving to a server-side Express + PostgreSQL architecture where the database is accessed only by your backend application user, --no-owner and --no-acl strip those cloud-specific role grants so the schema imports cleanly.

COMPANION CORNERSTONE REFERENCE GUIDE (/LIBRARY)

### Why Your Website Bill Should Not Depend on How Often It Is Used: Usage-Billed Cloud vs. Flat-Rate Hosting

Read the full 4,000+ word pricing and architecture comparison of usage-metered cloud platforms versus our flat-rate $99–$199/mo hosting (with active resource monitoring).

[Read Full Engineering Guide](https://www.greentreehosting.com/library/why-your-website-bill-should-not-depend-on-how-often-it-is-used)

PREDICTABLE FLAT-RATE CLOUD

### Ready to Move Your Website or App Onto Predictable $99–$199/mo Hosting?

We handle the complete migration off metered cloud platforms or legacy hosts into an isolated Docker + PostgreSQL 16 environment on our High-Availability Linux cloud—with 1 SmarterMail Enterprise mailbox included and active resource stewardship.

[Compare $99 & $199 Flat-Rate Cloud Plans](https://www.greentreehosting.com/hosting)[Read Usage-Billed vs. Flat-Rate Cloud Guide](https://www.greentreehosting.com/library/why-your-website-bill-should-not-depend-on-how-often-it-is-used)

RELATED FIELD NOTES & RUNBOOKS

## Related Notes From the Sysadmin Desk

[View All 8 Field Notes](https://www.greentreehosting.com/field-notes)

[Server Transfers & Cutovers9 min readThe Zero-Downtime Server Transfer Runbook: How We Move Live Websites, Databases, and Mailboxes Without Losing a Single Order or EmailExecute a 5-stage cutover: lower DNS TTLs to 60 seconds 48 hours early, stage and test via local hosts-file override, pre-issue TLS certificates, run a final sub-second rsync + database delta sync, and enforce a 5-source 301 redirect map.Open Field Note & Checklist](https://www.greentreehosting.com/field-notes/zero-downtime-server-migration-and-cutover-runbook)[Web App Security & Linux Ops7 min readLocking the Front Door on Modern Web Apps: Why Your Production Container Should Never Serve From the Project Root (Plus Our 8-Point Pre-Launch Gate)Enforce strict path.resolve(DIST_DIR) confinement with explicit 403/404 dotfile blocking, disable production .map files, keep secrets strictly server-side, and run an 8-point negative-testing gate before launch.Open Field Note & Checklist](https://www.greentreehosting.com/field-notes/docker-static-asset-isolation-and-8-point-pre-launch-security-gate)[DNS & Linux Infrastructure8 min readWritable Standby PostgreSQL Failback Merges: Why ON CONFLICT (id) DO NOTHING Silently Drops Rows on Sequential IDs (And How to Fix It With UUIDs or Split Sequence Ranges)Audit every table in the failback merge list: use UUID primary keys (DEFAULT gen_random_uuid()) on append-only lead/submission tables, or configure non-overlapping odd/even sequence steps (INCREMENT BY 2) dynamically above MAX(id)—and check secondary unique constraints and payload hashes before skipping.Open Field Note & Checklist](https://www.greentreehosting.com/field-notes/postgres-standby-failback-merge-id-collision-and-uuid-vs-sequence-ranges)
