<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Backend on Stratum Blog</title>
    <link>https://blog.stratum.jetzt/tags/backend/</link>
    <description>Recent content in Backend on Stratum Blog</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <copyright>2026 Andrew Zuo</copyright>
    <lastBuildDate>Wed, 15 Jul 2026 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://blog.stratum.jetzt/tags/backend/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Why I Rebuilt My RSS Backend in PocketBase and Go</title>
      <link>https://blog.stratum.jetzt/posts/2026-07-15-why-i-rebuilt-my-rss-backend-in-pocketbase-and-go/</link>
      <pubDate>Wed, 15 Jul 2026 00:00:00 +0000</pubDate>
      <guid>https://blog.stratum.jetzt/posts/2026-07-15-why-i-rebuilt-my-rss-backend-in-pocketbase-and-go/</guid>
      <description>&lt;p&gt;I spent the first few months of building Stratum using a conventional backend stack. You know the type: a framework with all the bells and whistles, an ORM layer that abstracted away database calls, and a collection of middleware that I barely understood but knew I needed. Everything worked fine until it did not. The RSS fetching logic grew more complex with each new feature, the AI summarization pipeline demanded careful rate limiting, and push notifications needed their own reliability guarantees. My codebase became a tangle of dependencies and configuration files that took longer to maintain than the features themselves.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>I spent the first few months of building Stratum using a conventional backend stack. You know the type: a framework with all the bells and whistles, an ORM layer that abstracted away database calls, and a collection of middleware that I barely understood but knew I needed. Everything worked fine until it did not. The RSS fetching logic grew more complex with each new feature, the AI summarization pipeline demanded careful rate limiting, and push notifications needed their own reliability guarantees. My codebase became a tangle of dependencies and configuration files that took longer to maintain than the features themselves.</p>
<p>The turning point arrived during one of those late night debugging sessions. I was tracing through a feed parsing bug and found myself navigating across seven different files just to understand where a single HTTP header was being set. The abstraction layers I had relied upon for convenience were now working against me. Every time I wanted to change something fundamental about how feeds were processed, I had to fight the framework instead of solving the problem.</p>
<p>That night I started reading about PocketBase. It is a backend in a single executable file, built in Go, with a built-in SQLite database and a surprisingly clean admin interface. The pitch was simple: instead of assembling dozens of libraries and services, you get authentication, file storage, real-time subscriptions, and API endpoints out of the box. The rest you write yourself in Go hooks. It sounded almost too straightforward, the kind of tool that promises simplicity but fails to deliver when you hit real complexity.</p>
<p>I decided to test it by rebuilding a small piece of Stratum&rsquo;s backend. The feed fetching and parsing logic seemed like a good candidate. Within a few hours I had a working prototype that could fetch an RSS feed, parse its contents, and store the items in the database. The code was readable. The error handling was explicit. And I could trace any request from beginning to end without jumping between framework conventions and library documentation.</p>
<p>The real surprise came when I started writing the AI summarization pipeline. In my previous setup, this had been scattered across multiple services with their own configuration and deployment concerns. In PocketBase, I wrote it as a Go hook that triggered after certain feed items were saved. The hook could call external AI APIs, store the results back in the database, and handle retries and failures with straightforward Go error handling. The entire flow lived in one logical place, and I could see exactly what was happening at each step.</p>
<p>Performance was another consideration. Go is fast, and PocketBase inherits that speed. Feed fetching and parsing happen concurrently, with careful rate limiting to avoid overwhelming source servers. The built-in SQLite database handles the storage layer without requiring a separate PostgreSQL instance or migration scripts. For a personal project that might serve thousands of users but does not need to scale to millions, this simplicity is a feature rather than a limitation.</p>
<p>There is a tradeoff, of course. PocketBase will not give you the distributed database capabilities of a cloud-native platform. You cannot horizontally scale it across multiple servers without additional tooling. If you are building the next Twitter, this is not your backend. But most RSS reader users do not need Twitter-scale infrastructure. They need a reliable service that fetches their feeds on time, stores their reading history, and delivers push notifications without dropping items. PocketBase delivers on those requirements without the operational overhead of managing multiple services.</p>
<p>The admin interface alone saved me countless hours. Being able to browse the database, inspect individual user records, and manually trigger debugging workflows from a web interface meant I could investigate issues without writing custom admin tools or connecting to a database client. When a user reported that a particular feed was not updating, I could check the feed entry directly, see the last fetch time, and trigger a manual refresh within seconds.</p>
<p>I also appreciate the transparency of the entire stack. PocketBase is open source, and the Go codebase is readable. When I encountered a limitation with the built-in authentication flow, I could read the source code to understand how it worked and extend it with my own logic. The hooks system lets you intercept events at various points in the request lifecycle, giving you the flexibility to add custom behavior without forking the entire project.</p>
<p>The migration from my previous backend was not trivial. I had to rewrite the feed parsing logic, restructure the database schema, and reimplement the push notification system using Firebase. But each piece I migrated became clearer and more maintainable. The code that processes Reddit RSS feeds through a proxy to avoid CORS issues is now a handful of Go functions instead of a separate service with its own deployment pipeline. The logic that detects hero images in article HTML and stores them for display lives alongside the feed parsing code where it belongs.</p>
<p>One thing that continues to surprise me is how well SQLite performs for this use case. RSS feeds are read-heavy workflows with relatively infrequent writes. The database mostly stores feed metadata, article content, and user preferences. SQLite handles this workload with ease, and the single-file deployment model means I do not need to worry about database connection pooling or replication lag. Backup and restore are straightforward file operations.</p>
<p>The Go ecosystem also deserves mention. The standard library is comprehensive, and the third-party packages I rely on—like goquery for HTML parsing and the readability library for extracting clean article content—are well maintained and performant. Writing in Go forces you to be explicit about error handling and type safety, which initially feels restrictive but ultimately produces more reliable code. When something goes wrong in production, the stack traces are clear and the bugs are easier to track down.</p>
<p>I am not suggesting that everyone should use PocketBase for their backend projects. Different tools serve different purposes, and the right choice depends on your specific requirements. For Stratum, the combination of PocketBase and Go has delivered a backend that is fast, maintainable, and easy to debug. The single executable deployment model means I can update the backend by swapping out one file and restarting the service. There are no dependency conflicts to resolve, no container orchestration to manage, and no complex configuration to maintain.</p>
<p>The result is a backend that I can understand entirely. When I write a new feature, I know exactly where the code lives and how it interacts with the rest of the system. When something breaks, I can trace the issue through the codebase without fighting against framework conventions. This clarity has let me iterate faster and ship features with more confidence.</p>
<p>Building tools for the web requires making choices about complexity at every turn. The temptation is always to reach for the most powerful tool, the one that promises to scale to any requirement. Sometimes the better choice is the simpler tool that solves your actual problem without dragging along a decade of accumulated abstraction. For Stratum, PocketBase and Go have been that choice, and I have no plans to change it.</p>
<div style="margin: 3rem 0 1rem 0; padding: 1.5rem; border: 1px solid var(--border); border-radius: 8px; text-align: center; background: var(--entry);">
	<h3 style="margin-top: 0; margin-bottom: 0.5rem; border: none; padding: 0;">Ready to get started?</h3>
	<p style="font-size: 0.95rem; margin-bottom: 1.5rem; color: var(--secondary);">Get Stratum now and take back control of your feed.</p>
	<div style="display: flex; justify-content: center; align-items: center; gap: 15px; flex-wrap: wrap;">
		
		<a href="https://apps.apple.com/us/app/stratum-full-text-rss-reader/id6445805598" target="_blank" rel="noopener" style="display: inline-block; transition: opacity 0.2s ease;">
			<img src="https://upload.wikimedia.org/wikipedia/commons/3/3c/Download_on_the_App_Store_Badge.svg" 
				 alt="Download on the App Store" 
				 style="height: 56px !important; width: auto !important; display: block !important; border-radius: 0 !important; box-shadow: none !important; background: transparent !important; padding: 0 !important; border: none !important;"
				 onmouseover="this.style.opacity='0.8'" 
				 onmouseout="this.style.opacity='1'">
		</a>
		
		<a href="https://play.google.com/store/apps/details?id=com.amorfatite.keystone" target="_blank" rel="noopener" style="display: inline-block; transition: opacity 0.2s ease;">
			<img src="https://upload.wikimedia.org/wikipedia/commons/7/78/Google_Play_Store_badge_EN.svg" 
				 alt="Get it on Google Play" 
				 style="height: 56px !important; width: auto !important; display: block !important; border-radius: 0 !important; box-shadow: none !important; background: transparent !important; padding: 0 !important; border: none !important;"
				 onmouseover="this.style.opacity='0.8'" 
				 onmouseout="this.style.opacity='1'">
		</a>
	</div>
</div>

]]></content:encoded>
    </item>
  </channel>
</rss>
