You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The backend runs on Heroku against expiring student credit, and solarsim.tech DNS points at Heroku (apex ALIAS + www CNAME to herokudns.com), with the Heroku dyno also serving the built SPA — Vercel hosts only services/pdf-service. A ready fallback matters, but Render's free tier is materially weaker than Heroku Basic and the plan must be honest about it rather than assume parity. Verified current terms: 512 MB RAM / 0.1 CPU, 750 free instance-hours per workspace per month, 100 GB egress, 500 build minutes, spin-down after 15 minutes idle with a 30–60 s cold start, no persistent disks, and no free-tier pre-deploy command (so the release: pnpm db:migrate:deploy step in the Procfile has no direct equivalent). Render's own free Postgres is disqualified — it expires 30 days after creation — which is why task 5 puts the database on Neon regardless of where compute runs.
The two real risks, stated up front: (a) 0.1 CPU against a pipeline that downloads multi-MB GeoTIFFs and runs sharp — Phase 11 §3 already documents OOM risk at 512 MB with a full Heroku CPU share, and Phase 11 §13 already flags that the frontend's 120 s PROCESSING_TIMEOUT_MS is tight; on a tenth of a CPU, new-location resolution will likely exceed it. (b) Cold start — a 30–60 s wait on the first click is a poor first impression for a link posted to LinkedIn. Task 11 is the mitigation for both.
Re-verify Render's current free-tier terms at implementation time; they changed as recently as Sept 2025 (spin-down moved 30 min → 15 min)
Verify custom-domain support and free managed TLS on Render's free instance type before committing — if the apex cannot be served for free, the fallback is a *.onrender.com demo URL, not a solarsim.tech cutover, and that changes the plan
Add .node-version pinned to the same major as engines.node (24) — Render reads it, and the repo currently has no Node pin file at all
Add a render.yaml blueprint: one free web service, buildCommand: pnpm install --frozen-lockfile && pnpm build, startCommand: pnpm start, health check path /api/health
Solve migrations without a pre-deploy hook: either append pnpm db:migrate:deploy to the build command (runs before the new instance goes live) or run it manually from a local shell against Neon and document the choice in RUNBOOK.md. Note the trade-off — a build-command migration runs on every deploy including failed ones
Deploy to Render as a parallel environment first; do not touch DNS until it is proven
Measure and record in the issue: cold-start time, RSS at idle, RSS while resolving a new location, and wall-clock time for one full Solar API pipeline run
Compare that pipeline time against the frontend's PROCESSING_TIMEOUT_MS; if it exceeds the ceiling, note that Phase 11 §13 becomes a prerequisite for a Render cutover rather than a nice-to-have
Do not add a keep-alive pinger that hits a database-touching route — per task 4, holding Neon's compute awake 24/7 costs ~180 CU-hours against a 100 CU-hour free budget and will suspend the database. If a pinger is used at all, point it at a route that touches neither Postgres nor the Solar API
Add the Render deploy as a second, non-default job or a documented manual step in .github/workflows/ci-cd.yml; keep Heroku as the active target until the credit actually runs out
Write a RUNBOOK.md cutover section: DNS records to change at Porkbun, env vars to set on Render, the APEX_DOMAIN / FRONTEND_URL / SITE_URL values, and the rollback path back to Heroku
verify: the Render deployment serves the SPA, GET /api/health returns ok, sign-in works, and a cached project loads end-to-end
verify: PDF export works from the Render origin — ALLOWED_FRONTEND_ORIGIN on the Vercel pdf-service must include the new origin or the export silently 403s (this exact regression already happened once, 26/04/26)
verify: the measured numbers are written into the issue so the Heroku-vs-Render decision is made on data, not vibes
Priority: High · Phase 12 task 10 of the maintainer's migration plan.
The backend runs on Heroku against expiring student credit, and
solarsim.techDNS points at Heroku (apex ALIAS +wwwCNAME toherokudns.com), with the Heroku dyno also serving the built SPA — Vercel hosts onlyservices/pdf-service. A ready fallback matters, but Render's free tier is materially weaker than Heroku Basic and the plan must be honest about it rather than assume parity. Verified current terms: 512 MB RAM / 0.1 CPU, 750 free instance-hours per workspace per month, 100 GB egress, 500 build minutes, spin-down after 15 minutes idle with a 30–60 s cold start, no persistent disks, and no free-tier pre-deploy command (so therelease: pnpm db:migrate:deploystep in theProcfilehas no direct equivalent). Render's own free Postgres is disqualified — it expires 30 days after creation — which is why task 5 puts the database on Neon regardless of where compute runs.The two real risks, stated up front: (a) 0.1 CPU against a pipeline that downloads multi-MB GeoTIFFs and runs
sharp— Phase 11 §3 already documents OOM risk at 512 MB with a full Heroku CPU share, and Phase 11 §13 already flags that the frontend's 120 sPROCESSING_TIMEOUT_MSis tight; on a tenth of a CPU, new-location resolution will likely exceed it. (b) Cold start — a 30–60 s wait on the first click is a poor first impression for a link posted to LinkedIn. Task 11 is the mitigation for both.Scope:
render.yaml(new),Procfile,package.json,.node-version(new),RUNBOOK.md,.github/workflows/ci-cd.ymlDepends on: #4, #5, #6, #7
Checklist
*.onrender.comdemo URL, not asolarsim.techcutover, and that changes the plan.node-versionpinned to the same major asengines.node(24) — Render reads it, and the repo currently has no Node pin file at allrender.yamlblueprint: one free web service,buildCommand: pnpm install --frozen-lockfile && pnpm build,startCommand: pnpm start, health check path/api/healthpnpm db:migrate:deployto the build command (runs before the new instance goes live) or run it manually from a local shell against Neon and document the choice inRUNBOOK.md. Note the trade-off — a build-command migration runs on every deploy including failed onesPROCESSING_TIMEOUT_MS; if it exceeds the ceiling, note that Phase 11 §13 becomes a prerequisite for a Render cutover rather than a nice-to-have.github/workflows/ci-cd.yml; keep Heroku as the active target until the credit actually runs outRUNBOOK.mdcutover section: DNS records to change at Porkbun, env vars to set on Render, theAPEX_DOMAIN/FRONTEND_URL/SITE_URLvalues, and the rollback path back to HerokuGET /api/healthreturns ok, sign-in works, and a cached project loads end-to-endALLOWED_FRONTEND_ORIGINon the Vercel pdf-service must include the new origin or the export silently 403s (this exact regression already happened once, 26/04/26)Priority: High · Phase 12 task 10 of the maintainer's migration plan.