Production Deployment Plan - Historical Netlify Baseline¶
Status: Historical reference; Netlify is no longer the live frontend host Date: March 12, 2026 Platform: Netlify (historical production baseline; rollback-only)
Update (March 12, 2026): Netlify deploys were restored and the application served successfully from the Netlify site,
https://wait-time.cawas live with a valid Let's Encrypt certificate,https://www.wait-time.caredirected to the canonical host, and production smoke passed against the canonical domain.Runtime usage controls implemented: -
/api/healthpolling reduced to every 5 minutes and only while tab is visible. - Read-heavy API routes now send short CDN cache headers (typically 2-10 minutes). - Admin, geolocation, and export routes areCache-Control: no-store.Direct-VPS note (March 13, 2026): the frontend is now live on the shared VPS and the active runtime path is documented in
docs/operations/direct-vps-frontend.md. Treat this file as historical Netlify baseline context only.
Current State¶
What's Already Built¶
- ✅ Backend scrapers: Python with GitHub Actions cron (hourly schedule active)
- ✅ Frontend: Next.js 14 with SSR, now deployed on the shared VPS
- ✅ Database: Neon PostgreSQL (already in production)
- ✅ CI/CD: GitHub Actions for scrapers, maintenance, and monitoring
What Needs Deployment¶
- No blocking deployment tasks remain
- Ongoing release discipline via explicit
[release]commits - Launch-material follow-through (LinkedIn post, screenshots, walkthrough)
Deployment Architecture Options¶
Option A: Static/SSG Hosting (Recommended for MVP)¶
Platforms: Vercel, Netlify, Cloudflare Pages
Pros: - Zero-config deployment for Next.js - Automatic builds on git push - Free tier generous (Vercel: 100GB bandwidth) - Built-in CDN and edge functions - Environment variable management in UI
Cons: - Vendor lock-in to some extent - SSR cold starts on free tier - Limited control over infrastructure
Best for: Quick launch, portfolio project, low operational overhead
Option B: Container Hosting¶
Platforms: Railway, Render, Fly.io, DigitalOcean App Platform
Pros: - More control over environment - Can run both frontend and backend services - Docker-based (portable) - Often includes database hosting
Cons: - Requires Dockerfile configuration - More setup complexity - Potentially higher cost - Need to manage container updates
Best for: Scaling beyond MVP, multiple services, specific runtime needs
Option C: Self-Hosted (VPS)¶
Platforms: DigitalOcean Droplets, Linode, Hetzner
Pros: - Complete control - Lowest cost at scale - Can run anything - SSH access for debugging
Cons: - Manual setup (nginx, SSL, etc.) - Requires devops knowledge - You manage security updates - No automatic scaling
Best for: Cost optimization, learning infrastructure, high control needs
Option D: Serverless Functions Only¶
Platforms: Vercel Functions, Netlify Functions, AWS Lambda
Pros: - Pay per execution - Auto-scaling - No server management
Cons: - Cold starts - Execution time limits (10s on Vercel free) - Not ideal for long scraper runs - Would need to refactor scraper architecture
Best for: Micro-services architecture (not recommended for current setup)
Historical Approach: Render (Superseded)¶
Platform: Render (container-based hosting)
- Frontend on Render
- Next.js support via Web Service
- Free tier available (with limitations)
- Auto-deploy from GitHub
-
Environment variables:
NEXT_PUBLIC_MAPBOX_TOKEN,DATABASE_URL -
Scrapers on GitHub Actions (already configured)
- Runs hourly on the live GitHub Actions path
- Connects to Neon PostgreSQL
-
No additional hosting cost
-
Database on Neon (already in production)
- Free tier: 512MB storage
- Auto-pause when idle
Total Cost: $0/month on free tiers (Render free tier has spin-down on inactivity)
Decisions Made¶
1. Frontend Hosting Platform¶
- Render (account created)
2. Custom Domain¶
- Use default Render domain (
*.onrender.com) for now - Custom domain may be purchased later
3. Alerts for Scraper Failures¶
- Pushover notifications (mobile push notifications)
- Required credentials:
PUSHOVER_USER_KEY,PUSHOVER_API_TOKEN
4. Hosting Tier¶
- Free tier (instances spin down after 15 min inactivity)
- First request after spin-down will be slow (~30s cold start)
- Upgrade to paid ($7/month) later if needed
5. Monitoring/Analytics¶
- Enable Render metrics dashboard (optional)
- Set up Sentry error tracking (optional)
- Monitor via GitHub Actions + Pushover alerts for now
User Actions Required¶
Once decisions are made above:
Step 1: Configure GitHub Secrets¶
Add to repository Settings → Secrets → Actions:
| Secret Name | Value | Required |
|---|---|---|
DATABASE_URL | Neon connection string | Yes |
PUSHOVER_USER_KEY | Pushover user key | Yes |
PUSHOVER_API_TOKEN | Pushover API token | Yes |
Getting Pushover credentials: 1. Create account at pushover.net 2. Install Pushover app on your phone 3. Your User Key is on the dashboard after login 4. Create an Application → get the API Token
Step 2: Deploy Frontend¶
Instructions will depend on platform chosen (see platform-specific guides below).
Step 3: Verify Deployment¶
- Frontend accessible at public URL
- Map displays with hospital markers
-
/methodspage loads - API routes returning data
- Scraper cron runs successfully
Platform-Specific Deployment Instructions¶
Render (Selected)¶
- Go to dashboard.render.com → Sign in
- "New" → "Web Service" → Connect GitHub repo
- Configure service:
- Name:
waittime-canada(or preferred name) - Root Directory:
frontend - Environment: Node
- Build Command:
npm install && npm run build - Start Command:
npm start - Add environment variables:
NEXT_PUBLIC_MAPBOX_TOKEN= (Mapbox token)DATABASE_URL= (Neon connection string)- Deploy
Notes: - Free tier instances spin down after 15 minutes of inactivity (first request may be slow) - Paid tier ($7/month) keeps instance running continuously - Deploys are release-gated in this repo; production deploy requires commit message containing [release] or [deploy]
If Vercel Selected (Alternative):¶
- Go to vercel.com → Sign in
- "Add New" → "Project" → Import GitHub repo
- Set Root Directory:
frontend - Add environment variables:
NEXT_PUBLIC_MAPBOX_TOKEN= (Mapbox token)DATABASE_URL= (Neon connection string)- Deploy
Configuration file needed: frontend/vercel.json
If Netlify Selected:¶
- Go to netlify.com → Sign in
- "Add new site" → Import from Git
- Build settings:
- Base directory:
frontend - Build command:
npm run build - Publish directory:
.next - Add environment variables (same as Vercel)
- Deploy
Configuration file needed: frontend/netlify.toml
If Railway Selected:¶
- Go to railway.app → Sign in
- "New Project" → Deploy from GitHub
- Add service: Frontend
- Root directory:
/frontend - Build command:
npm run build - Start command:
npm start - Add environment variables (same as above)
- Deploy
Configuration file needed: frontend/Dockerfile (optional but recommended)
If Cloudflare Pages Selected:¶
- Go to dash.cloudflare.com → Pages
- "Create a project" → Connect to Git
- Build settings:
- Framework preset: Next.js
- Build command:
npm run build - Build output directory:
.next - Root directory:
frontend - Add environment variables (same as above)
- Deploy
Note: Cloudflare Pages requires Next.js Edge Runtime compatibility
Risk Assessment¶
| Risk | Likelihood | Impact | Mitigation |
|---|---|---|---|
| Scraper fails silently | Medium | High | Heartbeat monitor (already configured) |
| Database connection limit hit | Low | Medium | Neon free tier: 100 connections, should be sufficient |
| API rate limits exceeded | Low | Low | No external APIs except Mapbox (generous free tier) |
| Storage exceeds free tier | Low | Medium | Enforce 30-day raw retention, keep aggregates permanent, and monitor table growth |
| Bad data published | Medium | High | Verification queue (already implemented) |
Post-Deployment Monitoring¶
After deployment, monitor for 24-48 hours:
- GitHub Actions
- Check scraper-cron runs hourly
- Verify heartbeat-monitor passes hourly
-
Watch for failure notifications
-
Frontend
- Test all pages load
- Verify data displays correctly
-
Check browser console for errors
-
Database
- Monitor connection count in Neon dashboard
- Verify measurements are being inserted
- Check retention cleanup / storage reporting runs as intended
Rollback Plan¶
If deployment fails or has critical issues:
- Frontend: Redeploy previous version via platform dashboard
- Scrapers: Disable GitHub Actions workflow temporarily
- Database: No changes needed (data persists)
Next Steps After Deployment¶
- Update README.md with live demo URL
- Update LinkedIn post with actual screenshots
- Monitor for 48 hours for stability
- Consider custom domain setup
- Begin planning Milestone 4 (Quebec expansion)
All Decisions Complete¶
All deployment decisions have been made. Ready to proceed with deployment:
- ✅ Platform: Render (free tier)
- ✅ Domain: Default
*.onrender.com - ✅ Alerts: Pushover notifications
- ✅ Tier: Free (with spin-down)
All decisions made. Ready for deployment.