SSD Nodes Learn Hosting plans →
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-13

Best RSS Reader for Small VPS: Miniflux vs FreshRSS

Compare Miniflux, FreshRSS, CommaFeed, yarr and Tiny Tiny RSS for memory, database needs, Fever and Google Reader API support, plus upgrade behaviour.

Which self-hosted RSS reader fit small VPS

Miniflux na self-hosted RSS reader wey fit go for small VPS. E dey run as one Go binary beside PostgreSQL. E support Fever and Google Reader APIs, so third-party phone apps fit connect, and upgrade na one docker compose pull. Choose FreshRSS instead if you want extensions and one container wey get SQLite inside.

Five readers dey worth the disk space for VPS: Miniflux, FreshRSS, CommaFeed, yarr and Tiny Tiny RSS. This page compare the things wey really different between dem: the memory wey each stack need, the database wey each one force you to use, the sync API wey your phone app need, and wetin go happen on upgrade day. Every figure here either come from the project or na plain arithmetic, and the text dey show which one. None of dem na benchmark for your hardware, so measure your own box with docker stats.

Di five readers, one paragraph each

Miniflux na Go software wey dey ship as one statically compiled binary. E documentation talk am plainly say e get one hard dependency: e "works only with PostgreSQL". SQLite mode no dey. E get REST API, Fever compatible API, and Google Reader compatible API, plus OPML import and export. PostgreSQL handle full text search, and na part of why database no be optional.

FreshRSS na PHP software wey dey run as one container wey hold both web server and application. SQLite na the default database and e no need second service, while PostgreSQL and MySQL dey supported for bigger installations. E support Google Reader API and Fever API. We don already cover the installation for our FreshRSS on a VPS walkthrough, so this page go compare am instead of repeating the installation.

CommaFeed na Java software for Quarkus, with layout wey copy Google Reader. Dem choose the database when dem build am, no be when e dey run, so the project publish one image for each database: athou/commafeed:latest-h2 for embedded H2 database, athou/commafeed:latest-postgresql for PostgreSQL, and other variants for MySQL and MariaDB. E expose REST API and Fever compatible API.

yarr (yet another rss reader) na one Go binary wey get SQLite embedded, and e no need container at all. Plain ./yarr dey listen on 127.0.0.1:7070. The flags short: -addr 0.0.0.0:7070 -auth alice:secret go open am to network behind password, and -db /data/yarr.db go put the database for the place wey you want. E get Fever compatible API. The newest tagged release na v2.8, from July 2024, checked August 2026, so treat am as finished software instead of software wey dem still dey develop actively.

Tiny Tiny RSS na the oldest among the five and the one wey heavy pass to run. The official Docker setup get four services: PostgreSQL container, PHP-FPM application container, separate updater container wey dey fetch feeds, and nginx container for front. The documentation talk plainly say "this setup uses PostgreSQL". E get im own JSON API, wey im Android client and some third-party apps dey use. Fever no dey part of am.

Memory wey each stack need

The figures wey follow na budgets, no be measurements: na the memory ceiling wey each stack suppose stay under for small VPS. CommaFeed number na the project own published example, wey cap the container for 256 MB. The other ones na ceilings wey leave extra room for the feed fetcher, because na that part dey spike when refresh cycle start.

ChartMemory ceiling per reader stack, in MB
The data behind this chart
[
  {
    "label": "yarr (SQLite)",
    "containers": 1,
    "mem_limit_mb": 128
  },
  {
    "label": "FreshRSS (SQLite)",
    "containers": 1,
    "mem_limit_mb": 256
  },
  {
    "label": "CommaFeed (H2)",
    "containers": 1,
    "mem_limit_mb": 256
  },
  {
    "label": "Miniflux + Postgres",
    "containers": 2,
    "mem_limit_mb": 320
  },
  {
    "label": "Tiny Tiny RSS",
    "containers": 4,
    "mem_limit_mb": 640
  }
]

yarr dey use the least memory at 128 MB because na one binary and one SQLite file, with no database server and no language runtime under am. Miniflux need 320 MB across 2 containers, and most of the memory dey go PostgreSQL, no be Miniflux. Tiny Tiny RSS na the outlier at 640 MB across 4 containers, because the application, updater, database, and web server na four separate processes with four separate heaps.

Set these ones as real limits, no be just hope. Memory limits for Docker Compose explain the syntax and wetin container dey do when e reach the ceiling. Container wey no get limit no go fail quietly when the whole machine memory don full: kernel go pick one victim process and kill am, and many times the victim no be the container wey cause the pressure.

Which database each reader forces on you

Na which database each of these five readers require, and this na their biggest operational difference. This decision bigger than any difference for user interface, because e decide how you go back up data and the risk wey upgrade fit bring.

Miniflux and the official Tiny Tiny RSS setup require PostgreSQL. E give you proper full text search and safe concurrent writes. But e require another container, one volume, and one recurring problem: official PostgreSQL images no fit migrate data between major versions in place. Tiny Tiny RSS documentation talk this one directly, and warn say "official PostgreSQL containers have no support for migrating data between major versions". Your practical options na to pin the old major version, or dump and restore with pg_dump and pg_restore. Plan to do this once every year or two.

SQLite na FreshRSS default and yarr default. Na one file, no server, no port, and no password. E dey work well for one person wey get few hundred feeds. E go slow when several users dey write at the same time. Na for this situation FreshRSS PostgreSQL option start to make sense. yarr add optional PostgreSQL support for v2.7, but the embedded file na the normal way to run am.

H2 na CommaFeed embedded default. E deserve some thought before you start, because CommaFeed choose its database when e build the image. Moving from H2 to PostgreSQL later no be configuration change. Na different image plus data migration wey you must do yourself. So decide before you don keep one year of read history for the box.

Your phone app go work?

This question dey decide pass wetin plenty people expect, because na only half of how people dey use feed reader the web interface be.

Miniflux dey support Fever compatible API and Google Reader compatible API, so most iOS and Android clients fit connect to am. FreshRSS dey support the same two, and e own documentation rank dem: Google Reader API na "best" with full feature support, while Fever API get "limited features and less efficient" behaviour. FreshRSS still need two steps before any app fit log in. Enable "Allow API access (required for mobile apps)" under Authentication, then create API password for user profile. If you skip the API password, app go show authentication failure while web login still dey work. This one fit confuse you until you know where to check.

CommaFeed and yarr both expose Fever compatible API and nothing else, so dem go work with Fever capable clients but no work with apps wey only speak Google Reader. Tiny Tiny RSS get e own API instead, so you need client wey dem write for am. Check say your preferred app support the reader before you import 300 feeds into am.

A working compose file for a 1 GB server

Na Miniflux stack be this, and e follow the project's own Docker example as of August 2026. The published port dey bound to loopback, the listen address dey set directly, and both containers get memory limit.

services:
  miniflux:
    image: miniflux/miniflux:latest
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:8080"
    depends_on:
      db:
        condition: service_healthy
    environment:
      - DATABASE_URL=postgres://miniflux:CHANGE_ME@db/miniflux?sslmode=disable
      - LISTEN_ADDR=0.0.0.0:8080
      - BASE_URL=https://rss.example.com/
      - RUN_MIGRATIONS=1
      - CREATE_ADMIN=1
      - ADMIN_USERNAME=admin
      - ADMIN_PASSWORD=CHANGE_ME_TOO
      - POLLING_FREQUENCY=60
    healthcheck:
      test: ["CMD", "/usr/bin/miniflux", "-healthcheck", "auto"]
    mem_limit: 128m
  db:
    image: postgres:18
    restart: unless-stopped
    environment:
      - POSTGRES_USER=miniflux
      - POSTGRES_PASSWORD=CHANGE_ME
      - POSTGRES_DB=miniflux
    volumes:
      - miniflux-db:/var/lib/postgresql
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "miniflux"]
      interval: 10s
      start_period: 30s
    mem_limit: 192m
volumes:
  miniflux-db:

Na three lines for that file people dey often set wrong. LISTEN_ADDR=0.0.0.0:8080 dey set because the binary documented default na 127.0.0.1:8080. Also, process wey bind to loopback inside container no fit receive connection through the published port. This one go give connection reset even when the container look healthy. The volume path /var/lib/postgresql match PostgreSQL 18. Version 17 and older dey store data for /var/lib/postgresql/data. If you mount wrong path, the data directory no dey on the volume at all, so all data go disappear when you recreate the container. 127.0.0.1:8080:8080 keep the port away from public internet. This na because publishing port without address dey write rule inside chain wey ufw no manage. Docker ports dey bypass ufw explain this mechanism, while a Traefik reverse proxy na how you put TLS in front of am.

docker compose up -d
docker compose ps
docker compose logs -f miniflux
docker stats --no-stream

docker compose ps suppose list both services as running, and the database suppose get healthy status. The first time Miniflux start, e go log the schema migrations. Na this RUN_MIGRATIONS=1 dey trigger. docker stats --no-stream go print the live memory column. Na that number you go compare with the limits for the chart above. If Miniflux container dey restart repeatedly, read the log. connect: connection refused mean say e start before PostgreSQL ready to accept connections. Na exactly this the service_healthy condition dey prevent, so check whether your edits still keep the condition. If Compose still new to you, Docker Compose basics for VPS explain the file layout first.

Wetin no go fit for 1 GB box

Tiny Tiny RSS na the one to skip. Its official four-service stack fit run for 1 GB VPS when that VPS no dey do anything else. But e no go run there together with another database-backed application and reverse proxy. Four services mean four sets of overhead, and PostgreSQL dey among dem.

CommaFeed fit work, but na only with H2 image and the 256 MB cap wey the project's own example set. The combination wey dey break small box na JVM beside separate database server, because JVM go use any headroom wey you leave am. CommaFeed documentation point to -Xmx256m as hard limit and OpenJ9 as "a more memory-efficient alternative to the HotSpot JVM". This show where the memory dey go.

When box run out of memory, the kernel out of memory killer go choose one process and terminate am. dmesg -T dey show line like Out of memory: Killed process 1234 (java), and the container go simply disappear from docker compose ps without message for application log, because the application never reach the point to write one.

How each one dey behave when you upgrade

  • Miniflux: docker compose pull && docker compose up -d, and e dey apply schema migrations when e start while RUN_MIGRATIONS=1 dey set. The upgrade risk no dey come from Miniflux. Na the PostgreSQL major version underneath am be the risk.
  • FreshRSS: pull the new image. If na SQLite, no database engine dey to upgrade, so the usual problem dey come from third-party extensions wey never keep up.
  • CommaFeed: pull the image variant wey match your database. Switching from latest-h2 to latest-postgresql no go carry your data across.
  • yarr: replace the binary and keep the database file. Since no release don come out since v2.8 for July 2024, checked August 2026, normally nothing dey to upgrade.
  • Tiny Tiny RSS: docker compose pull && docker compose up -d. Schema migrations run automatically, and the interface go redirect you to a migration screen when one need confirmation.

Make database dump before you upgrade any of these, no be after.

docker compose exec -T db pg_dump -U miniflux miniflux | gzip > miniflux-$(date +%F).sql.gz

Wetin refresh interval dey cost for bandwidth

The numbers below na arithmetic, no be measurement. Dem assume 100 feeds, one request for each feed per interval, and 40 KB for each response. Real traffic dey lower whenever server honour conditional requests, and e dey higher when feeds carry full article text.

ChartMonthly fetches and bandwidth for 100 feeds at 40 KB per response
The data behind this chart
[
  {
    "label": "Every 5 minutes",
    "fetches_per_month": "864,000",
    "gb_per_month": 34.6
  },
  {
    "label": "Every 15 minutes",
    "fetches_per_month": "288,000",
    "gb_per_month": 11.5
  },
  {
    "label": "Every 30 minutes",
    "fetches_per_month": "144,000",
    "gb_per_month": 5.8
  },
  {
    "label": "Every 60 minutes",
    "fetches_per_month": "72,000",
    "gb_per_month": 2.9
  }
]

Five-minute interval for 100 feeds na 864,000 requests and roughly 34.6 GB every month. Hourly polling na 72,000 requests and about 2.9 GB. Miniflux ships with POLLING_FREQUENCY set to 60 minutes. Na the last row for that chart, and that default dey okay for almost everybody. Article no go arrive early because you ask for am more often.

Conditional requests na wetin keep the real number below the arithmetic. Reader wey store the ETag and Last-Modified headers wey feed return go send dem back as If-None-Match and If-Modified-Since. Server wey get nothing new go answer 304 Not Modified without body. The connection still cost handshake, but e no cost the payload. Feeds wey ignore conditional requests go give you the complete document every time, so small number of large feeds fit use most of your transfer bill by themselves.

Hard polling fit also make dem block you. Server wey decide say you dey hammer am go reply 429 Too Many Requests, and some sites go answer 403 instead. Miniflux dey record the last error against the feed itself, so feed list na the first place to check when one feed stop updating while the others still dey work.

Feeds fit die, and OPML file no be backup

Feeds dey spoil faster than you expect. Domains fit expire, sites fit move go platform wey no get feed, and URL wey dey serve XML before fit start serve HTML error page with 200 OK status. Na this last one dey cause wahala: fetch succeed, parse fail, and your reader record parsing error instead of network error. Once every year, arrange feed list by last updated, then delete the ones wey don stop talking.

OPML export na your subscription list. E hold feed URLs and folder names. E no hold read state, starred articles, per-feed settings, filter rules, or article text wey you save. Import that OPML into fresh install, and you go get your feeds back, but every article wey you don read before go show as unread again.

The backup wey matter na the database. For PostgreSQL, the pg_dump command above na the complete job. For SQLite reader like FreshRSS or yarr, stop the writer and copy the file, or take consistent copy while e dey run with sqlite3 yarr.db ".backup '/tmp/yarr-backup.db'". Plain cp of database wey somebody dey write fit create file wey no go open later, because the copy fit capture write wey never finish. Then push those files comot from the box on schedule. Na wetin restic backups for VPS dey do. Restore one into scratch container at least once, so you go know say the procedure dey work.

Feed reader na one of the cheapest services to run by yourself. Na why e dey appear for every list of things wey worth self-hosting for 2026. Put SearXNG instance wey you self-host near am, and both your reading and searching go remain for hardware wey you control.

FAQ

Which self-hosted RSS reader uses the least memory?

yarr. E be one Go binary wey get SQLite compiled inside, so e no need database server or any language runtime apart from itself, and 128 MB limit dey okay. The trade-off na maintenance and features: e newest release na v2.8 from July 2024, and e only support Fever API. If you want project wey dem still dey develop actively with similar resource use, Miniflux plus PostgreSQL for 320 MB na better answer.

Can I run a self-hosted RSS reader on a 1 GB VPS?

Yes. Miniflux with PostgreSQL fit stay within about 320 MB when you set mem_limit for both containers, and FreshRSS with SQLite fit run inside one container. The one wey you suppose avoid for 1 GB na official Tiny Tiny RSS stack, wey get 4 services including its own PostgreSQL. Always set memory limits, because unlimited container for server wey memory don full fit make kernel kill one process, and many times na database e go kill instead of the application wey cause the problem.

Which of these work with iOS and Android RSS apps?

Miniflux and FreshRSS support both Fever compatible API and Google Reader compatible API, so almost any mobile client fit connect. CommaFeed and yarr only offer Fever API. Tiny Tiny RSS use its own API, so you need client wey dem build for am. For FreshRSS, you must also enable API access under Authentication and set separate API password for the profile. If you no do this, the app go fail to log in even though the website still dey work.

Is an OPML export a backup of my RSS reader?

No. OPML keep feed URLs and folders, so e fit rebuild your subscription list and nothing more. Read state, starred items, filter rules, and article text all dey inside database. Back up the database itself with pg_dump for PostgreSQL, or use .backup command for SQLite, then copy the result comot from the server.

Does Miniflux support SQLite?

No. The project documentation talk say e "works only with PostgreSQL", and PostgreSQL features dey implement full text search, so no lighter mode dey wey you fit switch to. If you want feed reader wey no need database container at all, run FreshRSS with its default SQLite backend or yarr with its embedded file.