Skip to content

Ask the docs

Ask anything about Tack.

Answers come from these docs, with links to the pages they’re from.

Answers are written by AI from these docs and can be wrong: check the pages they link to.

Costs and limits

Tack is designed to be self-hostable on a free plan, but what it costs you depends on how much it’s used, and on Cloudflare’s current prices and limits. This page says what Tack uses, so you can check it against them:

Product How Tack uses it
Workers One Worker, tack: the API, sign-in, webhooks and board connections
Static assets The app itself (HTML, scripts, fonts)
Durable Objects, SQLite storage One object per board, one per repository on a board, and two for the instance
Cron Triggers One, every ten minutes, to redeliver failed webhooks
Workers Logs Every log event
Workers AI AI suggestions: naming stacks, and AI on boards when someone asks (see AI)

No KV, R2, D1 or Queues.

  • People on boards. Each person on a board holds a WebSocket to that board’s object, which stays active while anyone’s connected (Tack doesn’t use WebSocket hibernation). Editing, moving and cursors are messages on it. While anyone’s connected, the board also renews its interest in its repositories every minute.
  • Repositories without the app, while a board is open: a check on GitHub every one to five minutes (see Repositories).
  • Webhooks, for repositories with the app: each delivery wakes its repository’s object, which tells the boards that have its items.
  • Widgets and inboxes: searches while someone’s looking, on a schedule from every minute (inboxes) to every 15 minutes, and after webhooks. Results are cached, and each board limits itself to 20 searches and 60 other reads a minute per person.
  • Pushes: one write a second, run from the board object’s alarm.
  • Storage: each board’s document (saved in chunks), its comments, push history, change log and history (up to 8 MB), backlink snapshots (each up to 1.5 MB, up to 1000 per board), and images (each up to 10 MB, up to 1000 and 256 MB per board, the same file kept once; one nothing shows or mentions is deleted after a week). Images live in the board’s object, not R2, so there’s nothing to set up for them. Repository objects cache their cards.
  • AI suggestions: a request to Workers AI each time a stack’s text settles on something it hasn’t been named for, and for each Auto-stack. Each is a few hundred tokens; each board asks at most 20 times a minute. Workers AI’s free daily allocation covers a lot of sessions; past it, it’s billed. Turn them off with TACK_AI=off.
  • Logs: one line per event; busy instances log a lot of webhook. and repo. events.
  • Images of public boards (embeds and link previews): drawing one takes a few hundred milliseconds of CPU time (more for a big board, and for PNG), and wakes the board’s object. Each image is drawn once for each change to what it shows: after that, browsers and GitHub’s image proxy are told it’s unchanged, and drawn images are kept in Cloudflare’s cache. Opening a public board’s page asks the board for a description of it, for link previews.

Besides naming stacks (above), AI on boards calls Workers AI only when an editor asks: once per request, or twice when the first answer for a widget doesn’t fit its settings. Nothing runs in the background. A request sends at most about 24,000 characters of board content and gets a short answer back, which with the default model (Gemma 4 26B A4B) costs a fraction of a cent; Workers AI includes a daily free allocation. Each board allows 12 requests a minute and 120 an hour, and each person 6 a minute, so a busy board can’t run up much. To make sure it costs nothing, set TACK_AI to off (Configuration), which turns stacks’ names off too.

GitHub Apps are free. What matters on GitHub is rate limits: card fetches are batched (50 items per GraphQL request), conditional polls cost nothing when nothing’s changed, searches are budgeted per board, and pushes are spaced a second apart. Every call to GitHub shares one backoff: once GitHub says a token is rate limited (its hourly budget, or a secondary limit for too much at once), nothing calls GitHub with that token until GitHub says it’s lifted, and pushes, widgets, comment commands and polling all wait for that same moment rather than retrying on their own. Widget and inbox searches run with each signed-in viewer’s own token, so they count against that person’s limits. Card fetches for repositories with the app use its installation token, shared by everyone on the instance, and checks on repositories without it borrow a watching viewer’s token, or GITHUB_TOKEN.