Fidder Overengineering Made Me Pay
Reduced Fidder's maintenance costs $17/month → $1/month by fixing architectural mistakes, like expensive Firestore secutiry rules and unnecessary VPS-polling.
I launched Fidder in September 2024 and it changed how I consume content. Instead of scrolling social media feeds full of noise, I get curated articles from writers I actually follow. Clean interface, hourly updates, zero algorithmic manipulation.
The app solved my specific problem perfectly. I was genuinely happy with what I'd built — a personal RSS reader that delivered exactly what I wanted without the chaos of modern content platforms.
Bills Started Arriving
Then the bills started coming.
January 2025: ~$12 USD from Firebase
February 2025: ~$10 USD from Firebase
Plus $5/month VPS for background workers
Total: ~$17/month for a personal RSS reader with one user.
Sure, nothing in the world is truly free, and $10-12/month isn't a "cost" for many people. But for projects meant to be free, you don't expect to pay $200+/year just to read RSS feeds.
Time to explore what was actually generating these costs.
Overengineering Made Me Pay
After digging into Firebase analytics, I discovered my "clever" architecture was the culprit.
I split data across multiple collections, forcing complex security rules with expensive database reads. I used a hybrid Firebase/VPS setup that seemed smart but created unnecessary complexity. I built custom authentication instead of using existing solutions.
Looking with fresh eyes, I found four expensive mistakes to fix:
Eliminate expensive security rules
Remove VPS infrastructure
Simplify authentication flow
Stop polling, use event-driven architecture
Security Rules That Cost $10/Month
My fragmented data structure forced complex permission checks:
// This line cost me $10/month
match /feeds/{feedId} {
allow read: if exists(/databases/$(database)/documents/users/$(req.user.id)) && get(/databases/$(database)/documents/users/$(req.user.id)).data.feeds[feedId] != null;
}
Every app interaction triggered expensive exists()
and get()
calls. Firestore charges per read operation, and I was generating hundreds of billable reads daily just to verify I could access my own data.
I moved everything under the user's path:
/users/{userId}/
├── feeds/{feedId}
└── posts/{postId}
This enabled simple, cheap security rules:
match /users/{userId} {
allow read, write: if userId == request.auth.uid;
}
As the result, the Firestore bill dropped from $12 to under $1.
VPS Infrastructure Added $5/Month Complexity
Another problem was, I split responsibilities between Firebase and a self-hosted VPS:
Frontend and database: Firebase
Background RSS workers: VPS
This created two systems to deploy and monitor, connection between VPS and Firebase, constant polling whether changes existed or not, and extra API calls.
I replaced VPS polling with Firebase Cloud Functions triggered by database events:
Feed validation:
onDocumentCreated
when user adds feedRSS checking:
onSchedule
runs hourlyPost processing: event-driven job queue
Functions only run when needed, not on empty polling cycles.
As the result, I eliminated $5/month VPS cost. Zero infrastructure management.
Job Queue System Prevents Timeouts
VPS-hosted background worker were procedural. They were long scripts that check database, fetch content from external source, do validation and save results back to database. It adds additional risk when small mistakes can break entire procedure.
With event-driven job queue in place, scheduler only orchestates workflow and passes jobs to future processors:
// Scheduler creates jobs
await scheduleJob({
type: 'check_feed',
user_id: userId,
feed_id: feedId,
});
// Function processes jobs automatically
export const processJob = onDocumentCreated({
document: 'jobs/{jobId}'
}, handleJob);
Currently, I have check_feed
, get_post
and check_digest
jobs.
This enables automatic retries, timeout prevention, and natural scaling. As the result, I have: reliable background processing without monitoring or babysitting.
Authentication Was Unnecessarily Complex
Fidder V2 used anonymous auth with custom device linking via 6-digit codes. Hundreds of lines managing cross-device sync for a problem that is solvable by introducing any kind of sign in.
I replaced anonymous auth + device linking with Google sign-in. Most likely, app users will have Google account.
Thanks to that, I got a really unique user ID, that enables automatic cross-device sync with zero authentication complexity. Also, I removed those hundreds lines of code.
All-In-One Platform Trade-Off
Moving to pure Firebase eliminated costs and complexity, but created new dependencies.
What I gained:
96% cost reduction ($17 → $0.75)
Single deployment pipeline
Unified monitoring and logs
Event-driven scalability
What I lost:
Infrastructure independence
Custom server capabilities
Protection from Firebase pricing changes
For personal or early-stage projects, this trade-off makes sense. I want maintainable, low-overhead tools. Our focus lies on core domain work, and we delegate boring parts to provider (Firebase in this case).
I also still love self-hosting. It is great when the entire stack is self-hosted. This gives full control, but also adds more overhead to you.
Each project requires its own analysis — there's no one-size-fits-all solution. Choose what you can handle and choose wisely.
Results
Total cost reduction: $17/month → $0.75/month (96% savings)
Codebase: 30% smaller
Infrastructure: One system instead of two
Maintenance: Minimal oversight required
The app still does exactly what I wanted — delivers curated content without social media noise. Now it actually costs what a personal project should: basically nothing.
Live: fidder.app