Cloud architecture

How I Use Docker, GCP, and Supabase to Scale Production Apps

Docker makes every deploy identical. GCP runs those containers close to users without idle VMs. Supabase gives production PostgreSQL, auth, and realtime so the app code can stay focused on the product.

Author

Published

Updated

Length

16 min · 2,400 words

Key takeaways

  • Docker is the unit of deploy: the same image runs locally, on Cloud Run, and in CI.
  • GCP is chosen for Asia-region pricing, Cloud Run scale-to-zero, Cloud SQL, and Cloud Storage.
  • Supabase is managed PostgreSQL plus auth and realtime - not a toy Firebase clone.
  • SVSFood and Ezlearn are the production proofs: kiosk APIs and an EdTech platform at 1,000+ MAU.
  • The stack is boring on purpose so a solo engineer can operate it.

Most portfolio sites list “Docker, GCP, Supabase” as chips. This article is how I actually scale client apps: what each layer is for, what I refuse to put on it, and how that showed up on SVSFood and Ezlearn.

The shape of the stack

I treat infrastructure as three contracts:

  1. Docker is how software is packaged. If it is not in an image, it is not what production runs.
  2. Google Cloud Platform is where images run and where files live. Cloud Run, Cloud SQL or a VPC path to Supabase, Cloud Storage, Secret Manager, Cloud Build.
  3. Supabase is production PostgreSQL with auth, Row Level Security, and realtime when the product needs live order or presence updates - accessed from app code through Prisma.

Frontends are often Next.js on Vercel when they are content and dashboard surfaces (Jara, LeetRun). APIs, workers, and anything that must stay warm or talk to hardware stay in Docker on GCP. Mixing those two is intentional, not indecision.

Docker as the unit of deploy

I containerize Node and Fastify services with multi-stage builds: a build stage with devDependencies, a runtime stage with only what the process needs. The image listens on a port, exposes a `/health` route, and reads secrets from the environment. Cloud Run starts that process, routes HTTPS, and scales the container count with traffic.

Why not a bare VM

A Compute Engine VM is fine as a jump box or for a stateful exception. It is a poor default for app servers. Patch levels drift. Node versions drift. “I SSH’d and npm installed” is not a rollback plan. Docker plus Cloud Run gives me immutable deploys: revert means serving the previous digest. That matters when you are on-call for a restaurant kiosk at dinner rush.

What goes in the image

  • The compiled or bundled API (Fastify + TypeScript).
  • Prisma client generated against the production schema.
  • A non-root user and a pinned Node LTS base.
  • No .env files. Secrets arrive from Secret Manager at runtime.

Local `docker compose` runs the API next to a Postgres that matches production (or a Supabase local stack). CI builds the same Dockerfile. The promotion path is an image tag, not a new ritual.

GCP as the runtime

I chose Google Cloud Platform for Ezlearn over AWS and over “put the whole product on Vercel” for three reasons that still hold:

  • Pricing and latency in Asia for Compute Engine and Cloud SQL were better for a bootstrapped EdTech targeting Indian learners.
  • Docker is a first-class citizen. Cloud Run is a container product, not an afterthought.
  • Cloud Storage plus a CDN is the correct place for course video, certificates, and kiosk assets - not the Node process.

Cloud Run for APIs

SVSFood’s Fastify API - kiosk, admin, website, rider - is the kind of service Cloud Run is for: bursty lunch and dinner traffic, idle overnight, needs HTTPS and a custom domain, must not require me to size a VM. Concurrency is tuned so one instance can hold multiple in-flight orders without melting. CPU is allocated only during request processing unless a WebSocket path needs a minimum instance.

Storage, SQL, and secrets

Ezlearn course video never streamed from the application server. Objects live in a bucket; the app mints URLs. Certificates are rendered server-side as PDFs and stored the same way. Secrets (payment keys, session material, third-party tokens) sit in Secret Manager and are mounted as env on the Cloud Run service. I do not keep production secrets in GitHub or in a Vercel dashboard for the API layer.

Supabase as the data plane

Supabase is PostgreSQL I do not have to baby-sit, plus auth and realtime when I want them. On SVSFood, Prisma talks to Postgres hosted on Supabase. Orders, inventory, menus, coupons, riders, and audit logs are relational on purpose. I will not put that in a document store and then re-implement joins in application code.

Auth and Row Level Security

For products where the client app can talk to the database under a user JWT, Supabase Auth plus RLS is a force multiplier. Admin consoles and payment webhooks still go through Fastify - those paths need server secrets and idempotency. The split is: Supabase for identity and row-level rules; custom API for money and vendors.

Realtime without a second architecture

Kiosk and rider status can move over Supabase realtime or over WebSockets on Fastify. I pick based on who owns the write path. If the write already goes through Fastify (inventory reservation, payment capture), I broadcast from there. If the write is a simple presence or chat-like update, Supabase realtime is enough. I do not run Redis “because scale” on a product that does a few thousand orders.

Case: SVSFood - four clients, one pipeline

SVSFood needed a kiosk, an admin console, an online ordering site, and a rider app. The constraint: one menu, one inventory, one order state. Docker packaged the Fastify API. GCP hosted it. Supabase PostgreSQL was the source of truth. Next.js handled console and website. React Native handled kiosk and rider. PhonePe and Petpooja stayed behind the API so a tablet never held a settlement key.

Scale here is not millions of QPS. Scale is correctness at dinner rush across three outlets, offline kiosks that sync, and an operator who can change a price once. The stack is sized for that. ₹7L+ in month one on owned devices is the outcome that matters.

Case: Ezlearn - EdTech on GCP for 1,000+ MAU

As CTO I owned architecture and shipping for Ezlearn: subscriptions, Hindi-first course delivery, AI learning roadmaps, certificates, a job portal. The platform ran on Next.js, Node, PostgreSQL, and GCP with 99.9% uptime and 1,000+ monthly active users. Video on CDN-backed storage kept the Node process small. Certificates were a server-side PDF pipeline into Cloud Storage. GCP’s Asia pricing made that viable for a bootstrapped company in Noida.

What I do not do

  • I do not run Kubernetes for a single API. Cloud Run is enough until it is not; I have not hit that wall on these products.
  • I do not put the database in a container on the same Cloud Run service as the API.
  • I do not use Supabase as a replacement for payment orchestration or complex vendor adapters.
  • I do not multi-cloud a client MVP. One cloud, one database, one container registry.

The architecture, simply

Vishu Pratap scales production apps by packaging APIs in Docker, running them on Google Cloud Run, storing relational data and auth in Supabase PostgreSQL (or Cloud SQL), and putting media on Cloud Storage. The pattern is proven on SVSFood’s food-tech stack and Ezlearn’s EdTech platform. Deeper notes: Docker in production, GCP architecture, Supabase and PostgreSQL.

Frequently asked questions

How does Vishu Pratap use Docker, GCP, and Supabase together?

Application servers (Fastify, Node) are packaged as Docker images and deployed to Google Cloud Run. Relational data, auth, and realtime live on Supabase PostgreSQL (or Cloud SQL when a project outgrows it). Object files go to Cloud Storage behind a CDN. The same Docker image is what ran in development.

Why Docker instead of deploying Node directly on a VM?

A VM drift problem - “it works on the server” - is expensive when you are the only operator. Docker pins the runtime, system libraries, and start command. Health checks, rolling deploys, and Cloud Run all assume a container contract.

Why Google Cloud Platform instead of AWS or only Vercel?

For Ezlearn, GCP won on Compute Engine and Cloud SQL pricing in Asia and on native Docker support. Vercel is excellent for Next.js frontends (Jara, LeetRun) but is the wrong home for long-running APIs, kiosk backends, and video-adjacent workloads. AWS would have worked; it was more expensive for the same region and shape.

When does Vishu use Supabase versus a custom Fastify API?

Supabase is the database, auth, and realtime layer. Custom Fastify or Node still owns payments, vendor integrations (PhonePe, Petpooja), and domain workflows. They are complementary: Prisma talks to the same Postgres Supabase hosts.
DockerGoogle Cloud PlatformSupabasePostgreSQLCloud RunScaling

Let's build together. Waiting to connect.

©2025Vishu Pratap · Software Developer