Skip to main content

Migrating from n8n & Render to Zero-Cost Serverless

Updated 4 min readMarkdown
Migrating from n8n & Render to Zero-Cost Serverless

Every morning at 09:00 AM, my Telegram bot sends an AI-prioritized checklist of active Notion tasks plus 1 curated article from my reading backlog. During the day, I text the bot to create tasks, archive links, or mark items done (done 1).

I ran this on self-hosted n8n (Render) + Supabase for two months. The drag-and-drop UI was great for prototyping. But on free tiers it was slow, and keeping it running 24/7 on paid servers would cost money every month. For simple personal workflows, I did not want to waste money; I wanted to save costs and make it fast.

Here is why free containers fell short and how I moved to a 100% free serverless stack.


Why I Moved Away from Free Containers

  1. 15-Minute Container Sleep: Render free web services freeze after 15 minutes of inactivity. Morning triggers hit 50 to 80-second cold starts or timed out completely.
  2. 30-Day Database Expiration: Supabase free PostgreSQL databases automatically pause after inactivity, corrupting n8n workflow execution state.
  3. 512MB RAM Crashes: Running Node.js, workflow history, and canvas UI routinely triggered Out-Of-Memory (OOM) kills.
  4. Local Laptop Limitations: Running scripts on a Mac fails whenever the laptop is closed, sleeping, or commuting at 09:00 AM.
  5. Unnecessary Cost: Paying $15 to $25/month for a 24/7 VPS just to run a 25-second morning cron and a few webhooks makes no sense.

The New Architecture: Two-Tier Serverless

I decoupled the workload into two serverless layers:

=============================================================================
TIER 1: REAL-TIME EDGE LAYER (Cloudflare Workers)
=============================================================================
[ Telegram User ]
        │
        ▼ (24/7 Webhook POST)
[ Cloudflare Worker: bot/index.js ]
        ├── 1. Natural Language Task Parsing ──► [ Notion Tasks DB ]
        ├── 2. Extract & Embed URLs          ──► [ Notion Reading DB ]
        └── 3. Interactive 'done 1' Sync     ──► [ Instant Reply: under 50ms ]

=============================================================================
TIER 2: SCHEDULED BATCH ENGINE (GitHub Actions)
=============================================================================
[ Daily Cron: 09:00 AM IST (03:30 UTC) ]
        │
        ▼ (Dispatches Ephemeral Cloud Runner)
[ GitHub Actions Ubuntu VM ]
        ├── 1. Queries Undone Tasks          ──► [ Notion Tasks DB ]
        ├── 2. Queries Unread Articles       ──► [ Notion Reading DB ]
        ├── 3. Executive AI Prioritization   ──► [ Gemini 3.5 Flash Lite ]
        ├── 4. Updates Status (Read = true)  ──► [ Notion Reading DB ]
        └── 5. Dispatches Numbered Briefing  ──► [ Telegram Morning Brief ]
        │
        ▼
[ Runner Shuts Down Automatically ] (Execution Time: ~25s | Cost: $0.00)

Tier 1: Real-Time Webhooks (Cloudflare Workers)

  • Platform: Cloudflare Workers (100,000 free requests/day, 0ms cold starts).
  • Natural Language Parsing: Texting "Remember to file tax returns next Monday" resolves the calendar date (2026-11-09), tags the domain, and creates the Notion page.
  • Link Preservation: URLs are extracted, saved into task summary, and embedded as rich blocks inside the Notion page body.
  • Interactive Completion: Replying done 1 or done 2 immediately marks that numbered item as Done in Notion via API.
  • On-Demand Reading: Texting /read fetches an unread article from the backlog anytime.

Tier 2: Scheduled Morning Batch (GitHub Actions)

  • Platform: GitHub Actions (2,000 free runner minutes/month).
  • Execution: Boots an ephemeral Ubuntu VM every morning at 03:30 UTC (09:00 AM IST).
  • AI Prioritization: Uses gemini-3.5-flash-lite (500 free requests/day) to format tasks into a numbered, double-spaced executive brief:
    1. Eat The Frog (single highest-impact task)
    2. Urgent deadlines
    3. Quick wins
  • Reading Backlog Buster: Queries Notion for Read != true, selects 1 random article, strips URL noise, marks Read = true, and appends the link with a remaining backlog counter.
  • Run Duration: ~25 seconds. Total monthly compute is ~12.5 minutes (0.6% of GitHub's free quota).

Comparison: Old vs New

Metric n8n + Render + Supabase Cloudflare + GitHub Actions
Monthly Cost $0 until trial expired, then forced paid $0.00 forever
Server Maintenance Managing Docker, DB migrations, node restarts Zero (100% serverless)
Webhook Latency 50-80s cold starts when asleep <50ms at global edge
Scheduled Quota Required external ping hacks 12 of 2,000 free mins/month (<1%)
Hardware Dependency Mac had to stay awake for local fallbacks Independent of laptop state
Failure Recovery Manual restarts and repairs Self-healing and stateless

Core Takeaway

Drag-and-drop workflow canvases work fine if you want to pay for cloud servers. But for personal workflows where the goal is to save money, code at the edge (Cloudflare) combined with ephemeral cloud cron (GitHub Actions) is faster, never sleeps, and costs $0.00.

No comments yet. Be the first to comment.