Free-tier deployment of MicroAI Paygate across three platforms. Total recurring cost: $0. No credit card required.
| Service | Host | Plan | Notes |
|---|---|---|---|
verifier/ (Rust) |
Render Web Service | Free | Public over HTTPS; stateless EIP-712 recovery |
gateway/ (Go) |
Render Web Service | Free | Public; calls verifier and OpenRouter, talks to Redis |
web/ (Next.js) |
Vercel | Hobby | Built from web/ subdirectory |
| Redis | Upstash | Free | Receipt store + nonce replay protection |
Both Render services share a region for low inter-service latency. Both sleep after 15 minutes of inactivity — the first request after sleep takes 30–50 seconds while the containers wake. The web app shows a warm-up banner during this window. See Cold-start behavior for details.
You'll need accounts on:
- Render — GitHub OAuth sign-up, no card required
- Vercel — GitHub OAuth sign-up, no card required
- Upstash — GitHub OAuth sign-up, no card required
- OpenRouter — free models are available (
z-ai/glm-4.5-air:freeby default)
And these values in hand:
OPENROUTER_API_KEYfrom OpenRouterSERVER_WALLET_PRIVATE_KEY— any 64-hex private key (demo only, never holds real funds)RECIPIENT_ADDRESS— the EIP-55-checksummed address derived from the key aboveREDIS_URLfrom Upstash (format:rediss://default:...@...upstash.io:6379)
Optional but recommended CLIs:
brew install render vercel-cli
render login # GitHub OAuth
vercel login # GitHub OAuth
render workspace set- Sign up at https://upstash.com using GitHub OAuth.
- Console → Create Database → choose Regional, pick the region nearest your eventual Render region (e.g. Mumbai/
bomor Singapore/sin), keep TLS enabled, leave eviction off for nonce-replay correctness. - Open the database → Connect to your database → copy the
rediss://URL (TLS). Save it — this isREDIS_URL.
Quick sanity check:
redis-cli -u 'rediss://default:...@...upstash.io:6379' PING # should print PONGThe verifier is stateless EIP-712 signature recovery. Public on Render's free tier — acceptable because it exposes no secrets and only does cryptographic recovery on caller-supplied inputs.
- Render dashboard → New + → Web Service → connect
AnkanMisra/MicroAI-Paygate. - Configure:
| Field | Value |
|---|---|
| Name | microai-verifier (or similar; becomes the URL subdomain) |
| Language | Docker |
| Branch | main |
| Root Directory | verifier |
| Region | Singapore (aws-ap-southeast-1) — closest free region for Mumbai Upstash; pick whatever matches your Upstash region |
| Instance Type | Free (default is paid — must change) |
| Docker Build Context Directory | verifier |
| Dockerfile Path | verifier/Dockerfile |
| Health Check Path | /health |
-
Environment variables (Advanced section):
CHAIN_ID=84532PORT=3002REDIS_URL=<your-upstash-rediss-url>VERIFIER_NONCE_STORE=redisVERIFIER_NONCE_KEY_PREFIX=microai:verifier:nonce:VERIFIER_REDIS_TIMEOUT_MS=2000
-
Click Deploy Web Service. First Rust build takes ~3–5 min.
-
Copy the assigned public URL — e.g.
https://microai-verifier.onrender.com. The gateway needs this URL in the next step.
Verify:
curl https://<verifier-app>.onrender.com/health
# {"status":"healthy","service":"verifier","version":"..."}- Render dashboard → New + → Web Service → same repo.
- Configure:
| Field | Value |
|---|---|
| Name | microai-gateway (must differ from the verifier's name) |
| Language | Docker |
| Branch | main |
| Root Directory | gateway |
| Region | same as verifier |
| Instance Type | Free |
| Docker Build Context Directory | gateway |
| Dockerfile Path | gateway/Dockerfile |
| Health Check Path | /healthz (note the trailing z — differs from the verifier) |
- Environment variables. Use Render's "Add from .env" button and paste the block below, then fill in the four
<...>placeholders with real values:
OPENROUTER_API_KEY=<your-openrouter-key>
OPENROUTER_MODEL=z-ai/glm-4.5-air:free
SERVER_WALLET_PRIVATE_KEY=<your-64-hex-key>
RECIPIENT_ADDRESS=<your-eip55-checksummed-address>
REDIS_URL=<your-upstash-rediss-url>
RECEIPT_STORE=redis
VERIFIER_URL=https://<verifier-app>.onrender.com
CHAIN_ID=84532
EXPECTED_CHAIN_ID=84532
PAYMENT_AMOUNT=0.001
ALLOWED_ORIGINS=*
TRUSTED_PROXIES=0.0.0.0/0
VERIFIER_TIMEOUT_SECONDS=60
PORT=3000Important:
RECIPIENT_ADDRESSmust be the canonical EIP-55-checksummed form, not lowercased or arbitrary-case. The browser wallet rejects malformed checksums withbad address checksumduring signing.CORS:
ALLOWED_ORIGINS=*is permissive; tighten it after web deploy in step 5.Verifier timeout: the default
2sis too short for Render free-tier cold-starts.60slets the verifier wake up during the first signed request.
- Click Deploy Web Service. Go builds take ~2 min.
- Verify:
curl https://<gateway-app>.onrender.com/healthz
# {"service":"gateway","status":"ok","timestamp":...}- Test the 402 challenge:
curl -i https://<gateway-app>.onrender.com/api/ai/summarize \
-H 'Content-Type: application/json' \
-d '{"text":"hello"}'
# HTTP 402
# {"error":"Payment Required","paymentContext":{...}}- Sign up at https://vercel.com using GitHub OAuth.
- Add New → Project → import
AnkanMisra/MicroAI-Paygate. - Configure:
| Field | Value |
|---|---|
| Project Name | microai-paygate (becomes the Vercel subdomain) |
| Framework | Next.js (auto-detected) |
| Root Directory | web |
- Environment Variables — add:
NEXT_PUBLIC_GATEWAY_URL=https://<gateway-app>.onrender.comNEXT_PUBLIC_VERIFIER_URL=https://<verifier-app>.onrender.com(lets the warm-up banner pre-wake the verifier too)NEXT_PUBLIC_POSTHOG_ENABLED=falseunless you are intentionally turning on Phase 1 analyticsNEXT_PUBLIC_POSTHOG_PROJECT_TOKEN=<your-posthog-project-token>when analytics is enabledNEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.comunless your PostHog project uses a different region/host
The four other NEXT_PUBLIC_* vars (EXPECTED_CHAIN_ID, EXPECTED_CHAIN_NAME, PAYMENT_AMOUNT, PAYMENT_TOKEN) have correct defaults baked into the code for Base Sepolia + USDC + 0.001. Set them only if you deploy against a non-default chain.
Phase 1 analytics is privacy-scoped to funnel metadata only. The web app does not send raw prompts, raw summaries, signatures, nonces, or full receipt payloads to PostHog.
- Deploy. ~1–2 min.
- Copy the assigned URL — e.g.
https://microai-paygate.vercel.app.
Go back to the gateway service on Render → Environment → update ALLOWED_ORIGINS from * to your exact Vercel domain:
ALLOWED_ORIGINS=https://<your-vercel-app>.vercel.app
This triggers an auto-redeploy. After ~1 min, preflight requests from the Vercel origin should still succeed; requests from any other origin will be blocked.
Verify:
curl -sI -X OPTIONS \
-H 'Origin: https://<your-vercel-app>.vercel.app' \
-H 'Access-Control-Request-Method: POST' \
https://<gateway-app>.onrender.com/api/ai/summarize | grep -i access-control-allow-origin
# access-control-allow-origin: https://<your-vercel-app>.vercel.app- Open
https://<your-vercel-app>.vercel.appin a browser. - You may see a "§ Free tier wake-up" banner at the top while the warm-up pings resolve.
- Connect MetaMask (or any EIP-1193 wallet) on Base Sepolia.
- Paste a paragraph of text into the form.
- Click Sign & Summarize.
- Wallet pops up — sign the EIP-712 typed-data payment context.
- Wait for: verifier validates → gateway calls OpenRouter → receipt is signed and returned.
- The receipt panel shows: summary text, signed receipt JSON, and a client-side signature verification badge.
If any step errors, check Render service logs for the gateway and verifier — both are visible from the Render dashboard.
Render's free tier sleeps web services after 15 minutes of no traffic. The first request after sleep takes 30–50 seconds while the container restarts. Mitigations baked into this project:
web/src/components/cold-start-warmup.tsxpings bothgateway/healthzandverifier/healthin parallel on first page load and shows a banner until they resolve. Subsequent requests are normal speed.VERIFIER_TIMEOUT_SECONDS=60on the gateway tolerates verifier cold-starts during signed requests.
These are good enough for portfolio / demo use. For an always-on production deployment, upgrade Render's Starter plan ($7/mo per service) or pivot to Fly.io (requires a card).
Use either the Render dashboard or the CLI:
# Render CLI — list services
render services
# Render REST API — update one env var (no CLI command yet exists for this)
RENDER_TOKEN=$(grep '^ key:' ~/.render/cli.yaml | awk '{print $2}')
curl -s -X PUT \
-H "Authorization: Bearer $RENDER_TOKEN" \
-H "Content-Type: application/json" \
-d "$(jq -n --arg v 'new-value' '{value: $v}')" \
"https://api.render.com/v1/services/<service-id>/env-vars/<KEY>"
# Trigger a redeploy
render deploys create <service-id>For Vercel env vars, use the CLI from the web/ directory:
vercel env add NEXT_PUBLIC_FOO production
vercel env rm NEXT_PUBLIC_FOO production.env.production.exampleand committed*.yamlfiles contain placeholders only.- Real values belong only in Render service env vars and Vercel project env vars.
- Never commit OpenRouter keys, private keys, Upstash URLs, or wallet material.
- Audit
.env*files before any push: they should appear in.gitignore.
If you'd rather pay for always-on hosting:
- Fly.io — requires a card on file but the same architecture maps cleanly (private networking between gateway and verifier via
.internalDNS). - Railway, Koyeb, Hugging Face Spaces — all support Docker. Refer to each platform's docs.
This guide is opinionated toward Render + Vercel + Upstash because that combination is genuinely zero-cost-zero-card and produces resume-credible URLs.