Issue tracking built around speed and one strong opinion about how work moves. Issues sit in cycles and projects, keyboard shortcuts cover almost everything, and the whole product is tuned so that filing and triaging costs seconds rather than minutes.
Build me an issue tracker that replaces Linear — and be honest about why this is ALMOST. **The speed is the product.** Linear feels instant because the whole workspace is in the client and every action applies locally before the server hears about it. That local-first sync engine is a hard engineering problem, not a feature you add later, and matching it is most of the project. The rest — issues, cycles, projects — is a fortnight. Decide up front whether you are building the fast version or the ordinary one, because retrofitting is not possible. STACK - Node 20+ with Fastify for the server - SQLite through better-sqlite3, WAL mode - The client holds the workspace in IndexedDB and evaluates every view locally - WebSockets for the change stream - Caddy in front THE LOCAL-FIRST ENGINE, WHICH IS THE DECISION - The client downloads the workspace once, then receives a stream of changes. Every list, filter and search runs against local data, so opening a view is instant with no request at all - Mutations apply locally, immediately, and are queued to the server. The interface never waits for a round trip - Each mutation carries a client-generated identifier and a base version. The server accepts or rejects, and the client reconciles — rolling back an optimistic change visibly rather than silently - Ordering by a server-side change counter, never a clock. A missed change means a client quietly showing stale data, so the client asks for everything since its last known counter on every reconnect - The workspace must fit in memory. Tens of thousands of issues do; millions do not. Write down that limit and what you would do past it — usually loading only recent and open issues, with the archive fetched on demand THE DATA MODEL - teams: id, key, name, cycle_duration_weeks, cycle_start - issues: id, team_id, number, title, description_md, state_id, priority, assignee_id, estimate, cycle_id, project_id, parent_id, position, created_at, completed_at, canceled_at, archived_at - states: id, team_id, name, type, position — the type is backlog, unstarted, started, completed or canceled. Custom names, fixed types, because every report depends on the type - cycles: id, team_id, number, starts_on, ends_on; cycle_issues with added_at and removed_at, so scope change is visible rather than invisible - projects: id, name, state, lead_id, target_date, team_ids_json; project_updates: id, project_id, body_md, health, at — written by a person, never computed - labels, comments, reactions, relations, attachments, subscriptions - issue_history: id, issue_id, field, old, new, actor_id, at — append-only, and where every metric comes from. It cannot be reconstructed later - Issue numbers per team, allocated in the creating transaction and never reused. That identifier goes into commit messages and lives forever THE OPINION, WHICH IS THE OTHER HALF - Cycles are fixed-length and automatic. Issues not finished roll to the next cycle, and the roll is recorded - One estimate scale per team, and it is a number, not a size name - A small set of state types, so a burndown is always computable - Triage as a real state for issues from outside the team - Resist configurability. The reason this product is fast to use is that there are few decisions to make, and every option you add is a decision somebody has to take before they can file a bug KEYBOARD FIRST - Every action has a shortcut, and a command palette covers the rest. Filing an issue should take under five seconds from anywhere - Multi-select in every list, with bulk actions - If a common path needs the mouse, it is a bug THE REST - Search across titles, descriptions and comments, running locally against the client's own copy, which is why it feels instant - Git integration: a branch or commit mentioning the issue key links it, and a merged pull request moves the state. Read the forge's events; never write to the repository - Notifications batched, with mentions immediate - Export everything as JSON in one command OPERATIONS - .env: DATABASE_PATH, STORAGE_PATH, BASE_URL, SESSION_SECRET, OIDC_*, SMTP_URL, FORGE_WEBHOOK_SECRET - Migrations on boot, each once; the change stream in its own process - Nightly backup off the machine, restore script - Health endpoint reporting connected clients and the newest change counter WHAT MATTERS MOST The sync engine and the history table. Build the local store, the change stream and optimistic mutation before a single screen looks good — that is the product, and the issue tracker on top of it is the easy part.
What you lose
- The speed: Linear's local-first sync engine is the product, and matching it is a hard engineering problem rather than a feature
- Keyboard-first interaction that a team internalises and then refuses to give up
- Two-way GitHub and Slack integration that stays working without you maintaining it
- Cycles, triage and project views that already encode a way of working
- The willingness of your team to move again, which you spend once
If you would rather not build
- GitHub Issues plus Projects, if you are already there
What it costs
read from their page 15 Aug 2026
| Plan | Billed monthly | Billed yearly | Last read |
|---|---|---|---|
| — | $10/mo | — | 15 Aug 2026 |
Their pricing page is where these came from. Seeing a different price? Tell us.
The escape hatch
open source · no votes, no paid placement
Plane
$0Issues, cycles and roadmaps in a similar shape, self-hosted.
makeplane/planefree · open source
Vikunja
$0Task and project management with list, kanban and gantt views.
go-vikunja/vikunjafree · open source
Why this verdict
our own opinion · changed only by a person
55/100
Verdict kinda at 55: issues, states and cycles are a weekend, but Linear's actual product is latency and a sync engine, and a slow clone of it will not survive contact with the team that already uses the fast one.
History
tracked since 6 Aug 2026 · nothing is ever overwritten
Questions about Linear
answered from the record above
Is Linear free?
No — the plan we track is $10 a month. Basic, $10 per user per month, billed yearly. The pricing page lists no month-to-month option for Basic or Business.
Can you replace Linear by building your own?
ALMOST. A weekend of work, and real gaps remain. Replacement score 55 out of 100, build time a weekend. Read what you lose before you decide.
How much does Linear cost?
$10 a month on Basic — $120 a year. Recorded 6 Aug 2026.
What do you lose by replacing Linear?
The speed: Linear's local-first sync engine is the product, and matching it is a hard engineering problem rather than a feature; Keyboard-first interaction that a team internalises and then refuses to give up; Two-way GitHub and Slack integration that stays working without you maintaining it; Cycles, triage and project views that already encode a way of working; The willingness of your team to move again, which you spend once. If any of those carry weight for you, keep paying.
Is there an open-source alternative to Linear?
Yes: Plane, Vikunja. The prompt on this page is for when you want it your way instead.
Related entries
same category first, most replaced first
Every week, something stops being worth paying for.
New verdicts, prices that moved, entries added. One email a week. Unsubscribe in one click. Nothing is being sent yet — your address is kept here, and the first issue is the first thing it is used for.
free forever · no tracking pixel · stored here, never passed to anyone

