How SlashFeed blocks an account everywhere at once — sessions, API tokens, MCP, background jobs — while deleting nothing, so unblocking restores it exactly. One timestamp, a handful of choke points, a query macro for the workers, and an email list with no foreign key on purpose.
Engineering Blog
Engineering deep-dives from the SlashFeed team — Elixir, Phoenix, and how the product is built.
Why a healthy domain can fail with :nxdomain on the BEAM — and the four fixes it took, in order, to stop 125 feeds a day dying of it: lower concurrency, an in-process retry, a local dnsmasq cache, and finally Erlang's own DNS client instead of macOS getaddrinfo.
How SlashFeed stops hammering a publisher that has started saying no — Hammer counters for the error rate, Postgres for the breaker state, a worker gate that cancels or snoozes jobs, a per-domain request budget, and an admin page to drive it all.
How SlashFeed delivers new-entry events to user-configured HTTP endpoints — the user_webhooks schema, an HMAC-SHA256 signing protocol receivers can verify, an Oban worker with retries and per-attempt delivery logging, and the fan-out that fires from the parser only for genuinely new entries.
A plain ON CONFLICT DO UPDATE writes the row even when nothing changed — every feed poll rewrites thousands of identical entries, bumping updated_at and burning WAL. One SQL clause, IS DISTINCT FROM, makes Postgres skip the no-op write. The catch: when it skips, RETURNING returns nothing and Ecto raises StaleEntryError. Here is the full pattern, the rescue trick that turns the error into an :unchanged result, and the three-layer RSS dedup strategy it sits inside.
Application-layer tenant scoping fails silently the day you forget a WHERE clause. PostgreSQL composite foreign keys turn a cross-user reference into a constraint violation the database rejects — here is the underdocumented references/2 :with option, the two migration patterns for CASCADE and SET NULL, the MATCH SIMPLE trick for nullable columns, and a test that proves the constraint lives in the DB.
How SlashFeed models trigger to condition to action automations as node and edge rows, evaluates them against feed events, and lets users build them on a drag-and-drop SVG canvas rendered entirely in LiveView.
How SlashFeed turns a blog or news listing page with no RSS feed into a subscribable feed using CSS selectors, Floki, and a small discovery toolkit.
How SlashFeed pulls entries from JavaScript-rendered SPA sites that have no RSS feed, using a headless Chrome sidecar and a dedicated Oban worker.
How the 🔥 Trending view ranks entries by aggregating saves and stars across users in a rolling seven-day window, scoped to your own subscriptions.
How SlashFeed prevents duplicate RSS entries through a three-layer strategy: GUID uniqueness, SHA-256 content hashing, and a PostgreSQL IS DISTINCT FROM guard that eliminates no-op writes on every fetch cycle.
How SlashFeed ships its REST API reference as a themed, in-app LiveView instead of a static Markdown file, and how it hands off to a downloadable Hoppscotch collection for real request execution.
How SlashFeed detects feeds that quietly stopped publishing and files self-resolving Kanban tickets with an idempotent Oban cron worker.
How I added Gmail-style j/k/m/o keyboard navigation to SlashFeed's entry list using a single LiveView hook — covering the input guard, LiveView stream DOM IDs, the updated() lifecycle gotcha, and pushEvent as the server bridge.
Why SlashFeed runs a third datastore — Cassandra via Xandra — next to PostgreSQL and ClickHouse, and how the BoringRSS.Cassandra client is wired so it can stay switched off until a real write path needs it.
How we built an admin image workbench to test OG-image transforms before they land in feed recommendations.
How SlashFeed's engineering blog is built with NimblePublisher — Markdown files compiled into a module attribute at startup, Makeup for syntax highlighting, a privacy-respecting view counter, and an RSS feed that the app can subscribe to itself.
How I added time-based one-time password (TOTP) MFA to SlashFeed using NimbleTOTP — the data model, the setup flow, backup code generation with bcrypt, and the subtle guard clause that prevents setup-state leakage.
How I built a four-layer onboarding system for SlashFeed using Driver.js, a single JSONB column, and an attach_hook trick that eliminated 34 boilerplate edits across every authenticated LiveView.
How I added a production-safe Model Context Protocol endpoint to SlashFeed — dual-mode auth with OAuth 2.0 PKCE and custom bearer tokens, an ETS bridge to pass identity through Anubis, and seven user-scoped tools — and the engineering decisions behind every layer.
What accessibility actually means in 2026, and how I built a site-wide accessibility settings widget for SlashFeed — bottom-left FAB, slide-up panel, CSS-driven overrides, localStorage persistence, zero server round-trips, and an Alt+A keyboard escape hatch.
How I added WebAuthn / passkey authentication to SlashFeed using the wax_ library — the data model, the JavaScript dance, the origin-binding gotcha that ate an afternoon, and the testing strategy for code that needs a real browser to fully exercise.
How I use Claude to develop SlashFeed: from idea to production.
Current RSS readers are either too bare, too expensive, or drowning in AI features nobody asked for. Here's why I built SlashFeed — and what I'm going to do about it in public.