Skip to content

#1 — Why Polling, Not Webhooks ​

The first architectural decision. Everything else follows from this.

The Question ​

When you want to react to GitHub events, there are two obvious approaches:

  1. Webhooks — GitHub pushes events to your endpoint
  2. Polling — you periodically ask GitHub "what's new?"

Every serious integration uses webhooks. It's real-time, it's efficient, it's the "right" way. So why did we choose polling?

The Problem with Webhooks ​

Webhooks need infrastructure:

  • A public URL (or ngrok, or a tunnel)
  • SSL certificates
  • Signature validation
  • Retry handling for missed deliveries
  • A web server that's always running and reachable

For a tool that's supposed to run on a laptop or a Raspberry Pi, that's a lot of overhead. The whole point of autosolve is "just run and forget." Webhooks are the opposite of that — they're "set up infrastructure and maintain it."

Why Polling Works ​

Polling is dumb, and that's its strength:

  • No public endpoint — runs behind any firewall, NAT, VPN
  • No infrastructure — no DNS, no SSL, no reverse proxy
  • Crash-safe — missed a cycle? Next one catches up. State is in SQLite.
  • Deployable anywhere — laptop, server, Raspberry Pi, Docker, systemd

The trade-off is latency. Webhooks react in seconds, polling reacts in minutes. For AI agent dispatch, minutes is fine. Nobody expects an AI to fix their bug in real-time.

The Cursor Pattern ​

To make polling reliable, we use a sync cursor — a bookmark that tracks where we left off:

  • since timestamp — only fetch issues updated after this point
  • page number — for paginating through large result sets
  • ETag — GitHub's conditional request header, returns 304 when nothing changed

The cursor is persisted in SQLite per repository. After a restart, polling resumes exactly where it stopped. No duplicate processing, no missed events.

What We Learned ​

Polling is unsexy but operationally simple. The complexity budget we saved on infrastructure went into making the polling loop robust — retry, backoff, rate limiting, cursor persistence. That turned out to be a much better investment.

Hindsight

We might add an optional webhook receiver later (it's on the Ideas list). But polling will always be the default — it's the zero-config path.


Commits: 0110a08 init → 65dcbf0 first issue polling

Apache 2.0 · Built in public · Contributions welcome