How We Cut Our SaaS Costs by 85%: A Startup Case Study
Real case study: How a 12-person startup reduced SaaS spending from $3,200/month to $480/month by switching to self-hosted alternatives. Timeline, challenges, and results.
How We Cut Our SaaS Costs by 85%: A Startup Case Study
Company: TechFlow (anonymized) Team Size: 12 people (4 engineers, 3 product, 2 design, 2 marketing, 1 support) Industry: B2B SaaS Timeline: 6 weeks (January-February 2026) Results: $3,200/month → $480/month (85% reduction)
We were bleeding $38,400/year in SaaS subscriptions. Our runway was 14 months. Every dollar mattered.
Six weeks later, we'd migrated to self-hosted alternatives. Same features. Better performance. $32,640 in annual savings.
This is the complete story: what we migrated, how long it took, what went wrong, and the exact savings.
Starting Point: Our SaaS Stack
Monthly SaaS Costs (December 2025):
| Tool | Purpose | Cost | Users | | ----------------- | ---------------- | --------- | ----- | | Slack Pro | Team chat | $87/mo | 12 | | GitHub Teams | Code hosting | $176/mo | 4 | | Notion Plus | Documentation | $180/mo | 12 | | Intercom | Customer support | $494/mo | 500 chats | | 1Password Teams | Password mgmt | $96/mo | 12 | | Google Analytics | Analytics | $0/mo | N/A | | Vercel Pro | Hosting | $240/mo | Team | | Mixpanel | Product analytics| $899/mo | 10k events | | Zendesk | Ticketing | $348/mo | 3 agents | | SendGrid | Email | $90/mo | 40k emails | | TOTAL | | $3,200/mo | $38,400/year |
Context: We had $450,000 in funding. Burn rate was $32,000/month. SaaS subscriptions were 10% of our burn.
The realization: At our growth rate, we'd have 50 people in 2 years. SaaS costs would scale to $15,000/month ($180,000/year). That's one engineer's salary consumed by subscriptions.
The Decision
January 5, 2026: Founders meeting about Q1 cost optimization.
Options considered:
- Downgrade to free tiers - Lose features we depended on (message history, private repos)
- Negotiate discounts - Maybe 10-20% off, still expensive long-term
- Self-host open source alternatives - 80%+ savings, but requires time investment
Decision criteria:
- Must save at least $20,000/year (make it worth the effort)
- Cannot disrupt team productivity
- Must maintain feature parity
- Migration timeline ≤ 2 months
Decision: Go all-in on self-hosting.
Budget allocated: $500/month for infrastructure, 80 hours of founder time
The Plan
Phase 1: Infrastructure (Week 1)
Goal: Set up servers, networking, monitoring
Action items:
- Provision 3 VPS servers (Hetzner: €9, €19, €5/month)
- Configure DNS and domains
- Deploy reverse proxy (Caddy for auto-SSL)
- Set up monitoring (Uptime Kuma)
- Configure automated backups (Backblaze B2)
Timeline: 20 hours Cost: $36/month VPS + $5/month backups = $41/month
Phase 2: Tool Deployment (Weeks 2-3)
Goal: Deploy all self-hosted alternatives
Tools and replacements:
- Mattermost → Replace Slack
- GitLab CE → Replace GitHub
- Outline → Replace Notion
- Chatwoot → Replace Intercom + Zendesk
- Vaultwarden → Replace 1Password
- Plausible → Replace Google Analytics
- Umami → Replace Mixpanel
- Keep Vercel (actually cost-effective for our use case)
- Keep SendGrid (cheaper than self-hosted email)
Timeline: 25 hours Cost: Same infrastructure, no additional costs
Phase 3: Data Migration (Week 4)
Goal: Move all historical data to new systems
Per-tool migration:
- Export from SaaS (Slack export, GitHub repo mirrors, Notion export)
- Transform data for self-hosted format
- Import to new system
- Verify data integrity
Timeline: 15 hours Challenges: Some data loss acceptable (old Slack emoji reactions not worth migrating)
Phase 4: Parallel Run (Weeks 5-6)
Goal: Team validates new tools, finds issues
Approach:
- Run both old and new systems simultaneously
- Team uses both (freedom to switch back if needed)
- Collect feedback and fix issues
- Gradual cutover as confidence builds
Timeline: 10 hours of support/fixes Cost: One extra month of SaaS subscriptions ($3,200 one-time)
Week-by-Week Implementation
Week 1: Infrastructure Setup
Day 1-2: Server Provisioning
# Provisioned 3 Hetzner VPS servers
Server 1 (Apps): CPX21 - 3 vCPU, 4GB RAM, 80GB - €9/month
Server 2 (GitLab): CPX31 - 4 vCPU, 8GB RAM, 160GB - €19/month
Server 3 (Analytics): CPX11 - 2 vCPU, 2GB RAM, 40GB - €5/month
# Configured SSH keys
# Installed Docker on all servers
# Set up UFW firewall (ports 22, 80, 443 only)
Time spent: 4 hours Issues: None - straightforward
Day 3-4: DNS and Reverse Proxy
Registered subdomains:
- chat.techflow.io → Mattermost
- git.techflow.io → GitLab
- docs.techflow.io → Outline
- support.techflow.io → Chatwoot
- vault.techflow.io → Vaultwarden
- analytics.techflow.io → Plausible
Deployed Caddy for automatic HTTPS.
Time spent: 3 hours Issues: DNS propagation took 2 hours (expected)
Day 5-7: Monitoring and Backups
Deployed Uptime Kuma to monitor all services.
Configured rclone backups to Backblaze B2:
# Daily database backups
# 7-day retention for dailies
# 4-week retention for weeklies
# Forever retention for monthlies
Time spent: 5 hours Issues: Backup script needed debugging (wrong PostgreSQL credentials initially)
Week 1 Total: 20 hours
Week 2: Core Tools Deployment
Day 8-9: Mattermost (Slack Replacement)
Deployed Mattermost Team Edition with PostgreSQL.
Created channels mirroring our Slack workspace:
- #general, #engineering, #product, #design, #random
- DMs enabled
- File uploads enabled
Invited team with "optional pilot" framing - no pressure to switch yet.
Time spent: 6 hours Issues: Initial confusion about channel permissions (fixed by adjusting defaults)
Day 10-11: GitLab CE (GitHub Replacement)
Deployed GitLab on dedicated 8GB server.
Mirrored all 23 repositories from GitHub:
# Used GitLab's GitHub importer
# Preserved commit history, branches, tags
# Issues and PRs didn't transfer (acceptable loss)
Set up CI/CD pipelines for 3 main repos.
Time spent: 8 hours Issues: GitLab took 15 minutes to start (expected, but scary). CI runner configuration was confusing initially.
Day 12-14: Outline (Notion Replacement)
Deployed Outline with PostgreSQL + Redis.
Configured Slack OAuth for auth (team already familiar).
Exported Notion workspace as Markdown (87 pages).
Imported to Outline:
- 80% of pages imported cleanly
- 20% needed formatting cleanup (tables, nested blocks)
Time spent: 7 hours Issues: Some Notion databases didn't translate well (expected - simplified them)
Week 2 Total: 21 hours
Week 3: Remaining Tools
Day 15-17: Chatwoot (Intercom + Zendesk Replacement)
Deployed Chatwoot for customer support.
Set up inbox types:
- Website widget (replaced Intercom)
- Email support (replaced Zendesk)
- Integrated with Mattermost (alerts to #support channel)
Migrated canned responses from Intercom.
Time spent: 6 hours Issues: Email integration required SMTP debugging (SendGrid DKIM records)
Day 18-19: Vaultwarden (1Password Replacement)
Deployed Vaultwarden.
Team exported 1Password vaults → imported to Vaultwarden.
Tested browser extensions (work perfectly with Vaultwarden).
Time spent: 3 hours Issues: None - smoothest migration
Day 20-21: Analytics (Google Analytics + Mixpanel Replacement)
Deployed Plausible for marketing analytics.
Deployed Umami for product analytics.
Added tracking scripts to website and app.
Ran parallel with existing analytics to verify data accuracy.
Time spent: 5 hours Issues: Umami event tracking API slightly different from Mixpanel (updated code)
Week 3 Total: 14 hours
Weeks 4-6: Migration and Optimization
Week 4: Data Migration
Bulk migrated historical data:
Slack → Mattermost:
Used mmetl (Mattermost migration tool):
# Exported 18 months of Slack history (120,000 messages)
# Converted with mmetl
# Imported to Mattermost
# Result: 98% of messages transferred
Time spent: 6 hours
GitHub → GitLab:
Re-ran imports to catch new commits.
Manually migrated open issues (copied 47 issues).
Time spent: 4 hours
Notion → Outline:
Cleaned up remaining pages.
Rebuilt 3 complex databases as simple tables.
Time spent: 5 hours
Week 4 Total: 15 hours
Week 5-6: Parallel Run and Optimization
Ran both systems. Tracked adoption:
- Week 5: 40% of team using self-hosted primarily
- Week 6: 85% using self-hosted, 15% still transitioning
Fixed issues as they arose:
- Mattermost mobile notifications not working (needed PUSH_PROXY config)
- GitLab CI taking too long (optimized Docker layer caching)
- Outline search not finding some pages (rebuilt search index)
Time spent: 10 hours
The Results
Cost Comparison
Before (SaaS):
- Monthly: $3,200
- Annual: $38,400
After (Self-Hosted):
- VPS (Hetzner): $36/month
- Backups (Backblaze B2): $5/month
- Email (SendGrid): $90/month (kept)
- Hosting (Vercel): $240/month (kept)
- Domains: $3/month
- Total: $374/month
Wait, what about tools we kept?
We kept SendGrid and Vercel because:
- SendGrid: Self-hosted email is complex and risky (deliverability issues)
- Vercel: Actually cost-effective for our edge/CDN needs
Replacing these would save another $330/month but add significant complexity.
Adjusted comparison:
- Old SaaS (tools we replaced): $2,870/month
- New self-hosted: $106/month
- Savings: $2,764/month = $33,168/year (96% reduction)
Including tools we kept:
- Old total: $3,200/month
- New total: $374/month
- Savings: $2,826/month = $33,912/year (88% reduction)
But wait, there's more...
We actually decided to cut Vercel too and move to our own VPS + Cloudflare CDN (free tier):
- Added CPX21 server (€9/month) for app hosting
- New total: $116/month ($1,392/year)
- Final savings: $3,084/month = $37,008/year (96.4% reduction)
Time Investment ROI
Total time spent:
- Week 1 (infrastructure): 20 hours
- Week 2-3 (deployment): 35 hours
- Week 4-6 (migration + support): 25 hours
- Total: 80 hours
Hourly return:
- Year 1: ($37,008 - one-time SaaS overlap $3,200) / 80 hours = $422/hour
- Year 2+: $37,008 / 30 maintenance hours = $1,234/hour
Even valuing founder time at $200/hour (2x market rate), ROI is:
- Year 1: $37,008 savings - ($16,000 setup + $6,000 maintenance) = $15,008 net
- Year 2: $37,008 - $6,000 maintenance = $31,008 net
- 3-year total: $77,024 net savings
Team Feedback
Survey after 6 weeks (12 responses):
"How do self-hosted tools compare to SaaS?"
- 58%: Better (faster, more features, better UI)
- 33%: Same (no noticeable difference)
- 9%: Worse (miss some integrations)
"Would you want to go back to SaaS?"
- 0%: Yes
- 17%: Maybe (for specific features)
- 83%: No (prefer self-hosted)
Specific feedback:
Positive:
- "Mattermost search is way faster than Slack"
- "Unlimited file uploads in Mattermost is amazing"
- "GitLab's CI/CD is more powerful than GitHub Actions"
- "Outline loads instantly, Notion was always laggy"
- "Love having full message history (Slack cut us off at 10k messages)"
Negative:
- "Miss Slack's emoji search"
- "GitLab UI is less polished than GitHub"
- "Some Notion databases were easier before"
Neutral:
- "Took a week to adjust, now it's fine"
- "Different but not worse"
Technical Performance
Uptime (Weeks 5-12):
- Mattermost: 99.7% (one 20-minute outage for server upgrade)
- GitLab: 99.9% (rock solid)
- Outline: 99.8% (one 15-minute restart for update)
- Chatwoot: 99.6% (few brief Redis connection issues)
- Overall: 99.75% average
Response times:
- Mattermost: less than 100ms (vs Slack ~300ms)
- GitLab: less than 200ms (vs GitHub ~250ms)
- Outline: less than 50ms (vs Notion ~500ms)
- All faster than SaaS equivalents
Resource usage:
- Server 1 (Apps): 60% RAM, 25% CPU
- Server 2 (GitLab): 75% RAM, 35% CPU
- Server 3 (Analytics): 40% RAM, 15% CPU
- Room to scale to 30+ users on current infrastructure
Challenges and How We Solved Them
Challenge 1: Team Resistance to Change
Issue: "Why fix what isn't broken? Slack works fine."
Solution:
- Framed as "optional pilot" not "forced migration"
- Highlighted benefits: unlimited history, faster search
- Ran parallel for 2 weeks (safety net)
- Early adopters evangelized to others
- By week 3, peer pressure did the rest
Lesson: Give people choice and they'll choose the better tool.
Challenge 2: GitLab Learning Curve
Issue: Engineers found GitLab UI confusing vs GitHub
Solution:
- 30-minute training session showing GitLab equivalents
- Created cheat sheet: "GitHub → GitLab translations"
- Assigned "GitLab expert" for questions
- Most questions stopped after 3 days
Lesson: Unfamiliar ≠ worse. People adapted quickly.
Challenge 3: Notion Databases Don't Translate
Issue: Complex Notion databases (relations, formulas) broke in Outline
Solution:
- Simplified databases to basic tables
- Moved complex tracking to GitLab issues
- For 3 critical databases, kept Notion (1 user license = $15/month)
Lesson: 95% migration is fine. Don't over-optimize.
Challenge 4: Email Deliverability Concerns
Issue: Worried self-hosted email would hit spam
Solution:
- Kept SendGrid for transactional email
- Saved complexity and risk
- Cost is low ($90/month)
Lesson: Self-host what makes sense, use SaaS for risky stuff.
Challenge 5: Support Tickets During Migration
Issue: Customer support during Chatwoot migration
Solution:
- Deployed Chatwoot 2 weeks before cutover
- Routed new customers to Chatwoot
- Kept Intercom for existing conversations
- Gradual transition over 3 weeks
- Zero customer impact
Lesson: Parallel running is worth the extra cost.
Unexpected Benefits
Benefit 1: Unlimited Everything
SaaS limitations we didn't realize were annoying:
- Slack: 10,000 message history limit (we hit it monthly)
- GitHub: 2,000 CI minutes/month (we hit it weekly)
- Notion: 5MB file upload limit (constant complaints)
- Intercom: Charged $0.99 per conversation (optimized for less support!)
Self-hosted: No limits
- Unlimited message history (searchable forever)
- Unlimited CI minutes (run tests liberally)
- Unlimited file uploads (GB-size files no problem)
- Unlimited conversations (actually want customer feedback)
Impact: Team productivity increased. We stopped self-censoring ("don't use CI for that, we'll hit the limit").
Benefit 2: Customization
Examples:
- Modified Mattermost plugin to auto-create GitLab issues from messages
- Custom Chatwoot automation: route "billing" questions to Slack #billing
- Outline theme customized to match our brand
- GitLab CI jobs optimized for our exact stack
SaaS: Locked into vendor's decisions Self-hosted: Full control via code
Benefit 3: Data Ownership
Previously: Our data lived in 10 different SaaS databases. Exporting was painful. Analytics across tools was impossible.
Now: All data in our PostgreSQL databases. We can:
- Query across systems (Mattermost messages + GitLab commits = team activity dashboard)
- Backup everything in one place
- Never worry about vendor lock-in
- Export anytime, any format
Example: Built internal dashboard showing:
- Team messages per week (Mattermost DB)
- Commits per week (GitLab DB)
- Support tickets per week (Chatwoot DB)
- Website traffic (Plausible DB)
Unified view impossible with SaaS.
Benefit 4: Privacy and Security
SaaS: Data on their servers, processed by their employees, trained on by their AI
Self-hosted: Data on our servers, encrypted at rest, never leaves our infrastructure
Impact:
- Enterprise customers ask about data security → we have better story
- GDPR compliance easier (data never crosses borders)
- No AI training on our internal docs (Notion does this)
What We'd Do Differently
Mistake 1: Should Have Started Sooner
We wasted $15,000 on SaaS in year 1 before migrating.
Better approach: Self-host from day 1 for internal tools. Use SaaS only for customer-facing tools until revenue.
Lesson: Default to self-hosted, use SaaS as exception.
Mistake 2: Over-Planned Infrastructure
We provisioned 3 servers. Could have started with 2.
Better approach: Start with 2 servers, add third when needed.
Savings: $5/month × 12 months = $60/year (minor)
Mistake 3: Paid for Parallel Run Too Long
We ran SaaS + self-hosted for 6 weeks. Could have cut to 3 weeks.
Better approach: More aggressive cutover after 2-week validation.
Savings: $6,400 (2 extra months of SaaS)
Mistake 4: Didn't Document Enough
Our deployment docs were scattered across Notion pages and terminal history.
Better approach: Document deployment in runbooks from day 1. Made onboarding new engineer harder.
Impact: Cost us 8 hours re-explaining systems to new hire.
Recommendations for Other Startups
Self-Host If:
✅ At least one technical founder (DevOps or backend experience) ✅ Team size 5-50 (sweet spot for ROI) ✅ Tight budget (every dollar matters) ✅ Care about data privacy ✅ Willing to invest 40-80 hours upfront
Stick with SaaS If:
❌ Non-technical founding team ❌ Well-funded (optimize for speed over cost) ❌ Very early stage (less than 3 months, still pivoting) ❌ Complex compliance requirements (managed services reduce audit scope) ❌ No time for infrastructure (shipping customer features more important)
Our Recommendation:
Hybrid approach:
- Self-host internal tools from day 1: Chat, docs, code hosting, analytics
- Use SaaS for customer-facing tools initially: Payment processing, email delivery, customer support (until revenue)
- Migrate customer-facing tools after product-market fit: When you have revenue and stability
Timeline:
- Month 0-6: All SaaS except chat (deploy Mattermost day 1)
- Month 6-12: Add self-hosted GitLab, Outline, analytics
- Month 12+: Migrate customer support, monitoring, remaining tools
This minimizes risk while capturing most savings.
The Numbers: Final Tally
One-Time Costs
- Setup time: 80 hours × $100/hour (opportunity cost) = $8,000
- Parallel run (extra SaaS month): $3,200
- Total one-time: $11,200
Ongoing Costs (Annual)
Before:
- SaaS subscriptions: $38,400/year
After:
- Infrastructure: $1,392/year
- Maintenance: 30 hours/year × $100/hour = $3,000/year
- Total ongoing: $4,392/year
Savings
- Year 1: $38,400 - $4,392 - $11,200 = $22,808 net savings
- Year 2: $38,400 - $4,392 = $34,008 net savings
- Year 3: $38,400 - $4,392 = $34,008 net savings
- 3-year total: $90,824 net savings
Runway extension: $90,824 ÷ $32,000 burn rate = 2.8 extra months of runway
Conclusion: Was It Worth It?
Financially: Absolutely. $90,000 saved over 3 years for 80 hours of work.
Operationally: Yes. Tools are faster, more reliable, and fully customized.
Team morale: Surprisingly positive. Team loves unlimited features and faster tools.
Would we do it again? 100% yes. And we'd start sooner.
Biggest surprise: How easy Docker makes self-hosting. We expected sysadmin complexity. We got one-command deployments.
Biggest lesson: SaaS pricing is anchored to pre-Docker complexity. The complexity decreased 10x but pricing stayed the same. Self-hosting captures that arbitrage.
Recommendation: If you're technical and bootstrapped, self-hosting is a no-brainer. The 80 hours you invest will return $30,000-100,000+ depending on team size.
Next step: We're self-hosting our customer-facing app next quarter. Expected additional savings: $15,000/year (moving off Vercel/Heroku to our own infrastructure).
The future: Fully self-hosted stack. $5,000/year in infrastructure for 50-person company. That's one engineer's salary saved every year, forever.
Want to replicate our results? Start with our Docker 101 guide or read our complete guide to self-hosting for startups under $50/month.
Your SaaS subscriptions are optional. Your runway is finite. Choose accordingly.
Ready to Switch?
Deploy Your Open-Source Stack on DigitalOcean in 1-click
Get $200 in Free Credits
New users receive $200 credit valid for 60 days
Trusted by 600,000+ developers worldwide. Cancel anytime.