How I Built Rollgate: From Side Project to Feature Flags SaaS
How I Built Rollgate: From Side Project to Feature Flags SaaS
Over the past year, I built Rollgate, a SaaS platform for feature flag management. The goal was simple: offer the same capabilities as LaunchDarkly — gradual rollouts, user targeting, A/B testing, kill switches — without the $70k/year enterprise price tag.
In this article, I share the technical journey: architectural decisions, all the features I implemented, mistakes made, and the real numbers behind a SaaS built by a single developer.
The Problem
Anyone who has worked in a development team knows the situation: you want to release a feature, but you're not sure it works for all users. Traditional deployment is a binary event — either the feature is live for everyone, or for no one.
Feature flags solve this by separating deployment from release. You can deploy code to production and enable it gradually: first 1% of users, then 5%, then 25%, and so on. If something goes wrong, you turn off the flag in a second — no rollback, no hotfix, no downtime.
Tools like LaunchDarkly do exactly this, but cost $25k to $150k per year. For a startup or mid-size team, that's prohibitive. I thought: can I build something equivalent and offer it at a fraction of the price?
Choosing the Tech Stack
The first fundamental decision was the stack. I had two non-negotiable requirements: low latency (feature flags are evaluated on every request) and operational simplicity (fewer moving parts means fewer things to break).
Backend: Go
I chose Go for the backend API for three reasons:
- Performance — A flag evaluation must happen in microseconds. Go compiles to native binary, has no significant GC pauses, and handles thousands of concurrent connections with goroutines.
- Simple deployment — A single static binary. No runtime, no dependencies. The final Docker image weighs 20MB.
- Excellent stdlib — HTTP server, JSON encoding, crypto, testing — all built-in. Fewer external dependencies means less surface area for bugs.
The router is Chi, lightweight and net/http-compatible. No heavy frameworks — I prefer composition over convention.
Frontend: Next.js
For the dashboard, I chose Next.js with React and Tailwind CSS. It provides SSR/SSG for marketing pages (SEO), API routes for backend proxying, and a smooth dev experience.
Database: PostgreSQL + Redis
PostgreSQL for persistence: JSONB for flag metadata, partial indexes, LISTEN/NOTIFY for cache invalidation. 29 tables, 67 indexes, 29 foreign keys.
Redis as cache layer for flag evaluations. When an SDK asks "is flag X enabled for user Y?", Redis serves the answer in milliseconds, updated in real-time via pub/sub.
Rollgate's Feature Set
Rollgate isn't a simple toggle on/off. I implemented a complete set of features covering the entire software release lifecycle.
Feature Flags with Multiple Types
Flags support four value types:
- Boolean — Classic on/off. Perfect for kill switches and feature toggles.
- String — Returns text. Ideal for A/B testing ("variant-a", "variant-b") or dynamic messages.
- Number — Returns a numeric value. Useful for configuring limits, percentages, or algorithm parameters.
- JSON — Returns a structured object. For complex configurations like layouts, plan-specific feature sets, or business rules.
Gradual Rollouts
Percentage rollout enables a flag for a specific percentage of users. Distribution uses consistent hashing (MurmurHash3) on the user ID, so the same user always gets the same result without saving state:
hash = MurmurHash3(flagKey + userId) % 10000
isEnabled = hash < rolloutPercentage * 100
Precision to 0.01%. You can go from 1% to 5% to 25% to 100% gradually, monitoring metrics at each step.
User Targeting and Segments
Targeting enables flags for specific user groups based on attributes:
- User attributes — Email, plan, country, app version, any custom attribute
- Operators — equals, contains, startsWith, endsWith, regex, in, greaterThan, lessThan
- Reusable segments — Define "Beta Users" or "Enterprise Customers" once, use in all flags
- Combined rules — AND/OR logic across multiple conditions
Kill Switches
The kill switch is the most critical production feature. When something goes wrong — a bug, a performance issue, a third-party integration down — you need to disable a feature instantly.
In Rollgate, every flag has a toggle that takes effect in seconds via real-time SSE propagation. No deploy needed, no server access required, you don't even need to be a developer. A product manager can kill a feature from the dashboard on their phone.
I've seen enterprise teams take 30-45 minutes for a traditional rollback (revert commit, CI, deploy, verify). With a kill switch, it's 2 seconds. During a production incident, those 30 minutes can cost thousands in lost revenue.
Scheduled Changes
Scheduled changes let you program flag modifications for a specific date and time:
- Coordinated launch — "Enable the new feature Friday at 2 PM when marketing publishes the blog post"
- Temporary promotions — "Enable the Black Friday banner from Friday to Monday"
- Automatic progressive rollout — "1% Monday, 10% Wednesday, 50% Friday, 100% next Monday"
- Feature sunset — "Disable the old API on April 1st"
Each scheduled change appears in the flag's timeline with pending/executed/cancelled status. A server-side cron job checks every minute for changes to apply.
Instant Rollback
Every flag modification is saved in history with timestamp, author, and complete state snapshot. Rollback restores the exact flag state at a previous point — not just the value, but also targeting rules, percentages, and scheduled changes.
It's different from a simple "undo": you can go back 5 changes, or to a specific dated version. The audit log tracks who did what and when.
A/B Testing
String variant flags enable native A/B testing. Instead of simple true/false, the flag returns a variant ("control", "variant-a", "variant-b") with configurable percentage distribution.
Evaluation tracking records which variant was served to each user, with timestamp and context. This allows correlating variants with business metrics in your preferred analytics tool.
I deliberately didn't build an integrated statistical engine — I prefer teams use their existing analytics tools rather than creating another data silo.
Multi-Environment
Every project has separate environments: development, staging, production (and as many as you want). Flags are independent per environment — you can have a flag active in staging but off in production.
Each environment has its own API keys (server and client), targeting rules, and history. This prevents the classic "oops, I modified the production flag thinking it was staging" mistake.
Audit Log
Every platform action is recorded in an immutable audit log: who created/modified/deleted a flag, what changed (before/after diff), when (precise timestamp), from which IP and user agent.
Retention varies by plan: 3 days (Free), 14 days (Starter), 90 days (Pro), 1 year (Growth). For compliance and debugging, having a complete trace is essential.
Webhooks
Webhooks notify external systems when a flag changes. Every create, update, or delete sends an HTTP POST to configured URLs with the full event payload.
Use cases: notify Slack when a production flag changes, trigger a deploy, update monitoring, sync with project management tools. Webhooks have automatic retry with exponential backoff and delivery logging.
Analytics and Usage Tracking
Rollgate tracks flag evaluations in real-time: how many times evaluated, unique users, true/false distribution, trends over time. Usage limits are per plan: 500K requests/month (Free), 1M (Starter), 3M (Pro), 12M (Growth).
13 SDKs
I built 13 SDKs covering all major languages and frameworks:
- JavaScript/TypeScript — sdk-core, sdk-node, sdk-browser, sdk-react, sdk-vue, sdk-angular, sdk-svelte
- Mobile — sdk-react-native, sdk-flutter
- Backend — sdk-go, sdk-java, sdk-python, sdk-dotnet
All SDKs share the same features: local cache, circuit breaker, retry with backoff, event buffering, and real-time SSE updates. If the server is down, SDKs continue working with cached values.
import { RollgateProvider, useFlag } from '@rollgate/sdk-react';
function App() {
return (
<RollgateProvider apiKey="rg_client_your_key">
<Dashboard />
</RollgateProvider>
);
}
function Dashboard() {
const showNewFeature = useFlag('new-dashboard', false);
return showNewFeature ? <NewDashboard /> : <LegacyDashboard />;
}
System Architecture
Client SDK → API Server (Go) → Redis Cache → PostgreSQL
↑
SSE Connection (real-time updates)
Flag evaluation happens in ~200μs. P99 latency is under one millisecond. The system supports tens of thousands of simultaneous SSE connections.
Technical Challenges
Race Conditions on Updates
When multiple users modify the same flag simultaneously, I use optimistic locking with a version counter. If someone else modified the flag in the meantime, the operation returns 409 Conflict.
Circuit Breaker in SDKs
If the API server is down, SDKs must not crash the host app. The circuit breaker has three states (Closed, Open, Half-Open) with exponential retry and request deduplication.
SEO for a SaaS App
I separated marketing and dashboard with a domain split: rollgate.io for SEO pages (Server Components) and app.rollgate.io for the authenticated dashboard.
Resilience and Monitoring
- Daily backups — PostgreSQL dump every night to a geographically separate server
- Monitoring — Prometheus + Grafana + Alertmanager with real-time alerts
- Health checks — Automated verification of API, Web, DB, Redis every 60 seconds
- Disaster recovery — Automated script rebuilds the entire stack in ~20 minutes
- SDK resilience — Local cache + circuit breaker = works even offline
The Numbers
| Metric | Value |
|---|---|
| Go files (non-test) | 147 |
| TypeScript/TSX files | 168 |
| API endpoints | 114 |
| DB tables | 29 |
| Total tests | ~850 |
| Published SDKs | 13 |
| Codebase score | 7.86/10 |
What I Learned
1. Simplicity Wins
Kubernetes in production? No, Docker Compose is enough. Microservices? No, a modular monolith is simpler. Every added complexity has a maintenance cost that must justify its weight.
2. Tests Save Lives
With ~850 tests, I can refactor with confidence. CI runs everything on every PR and blocks deployment if something fails.
3. Billing Is Harder Than the Product
Paddle for payments was surprisingly complex: webhooks, subscription lifecycle, prorating, dunning, tax handling. Use a payment provider that handles everything (Paddle, Lemon Squeezy) rather than raw Stripe.
4. SEO Requires Constant Attention
If Google doesn't index you, nobody will find you. I spent weeks on SSR, JSON-LD, sitemaps, meta tags. It never ends.
5. Building Solo Is Sustainable (With Limits)
Code is the easy part — finding users is the real challenge. Marketing, support, and growth require different skills.
What's Next
Rollgate is live at rollgate.io with a generous free tier (500K requests/month). Next: advanced A/B testing with auto-winner, teams with SSO, self-hosted version, and complete OpenAPI spec.
The Market: Competitors and Positioning
The feature flags market is dominated by a few players with aggressive enterprise pricing:
| Platform | Pricing | Strengths | Limitations |
|---|---|---|---|
| LaunchDarkly | From $833/mo | Market leader, enterprise-ready, vast integrations | Prohibitive for startups, excessive complexity |
| Flagsmith | From $45/mo | Free self-hosted, API-first | Less polished UI, fewer SDKs |
| Unleash | From $80/mo | Mature self-hosted, good docs | Complex setup, dated UI |
| PostHog | Usage-based | Complete suite (analytics + flags), open-source | Flags aren't the focus, overhead |
| Rollgate | Free → €45/mo | Accessible pricing, 13 SDKs, 5-min setup | New to market, growing community |
Choosing the Pricing Model
Pricing was one of the hardest decisions. I studied every competitor and identified three approaches:
- Per-seat (LaunchDarkly) — Scales with team size, penalizes large companies. $70k/year for 50 developers isn't unusual.
- Usage-based (PostHog) — Scales with traffic, unpredictable for budgeting. Can explode with traffic spikes.
- Fixed tiers (Rollgate) — Predictable pricing, scales by features and limits. Customers know exactly what they pay.
I chose fixed tiers because cost predictability is essential for startups and SMBs. The four plans:
| Plan | Monthly | Annually | Requests/mo | Team | Target |
|---|---|---|---|---|---|
| Free | €0 | €0 | 500K | 3 members | Side projects, MVPs |
| Starter | €45/mo | €39/mo | 1M | 5 members | Early-stage startups |
| Pro | €119/mo | €99/mo | 3M | 15 members | Growing teams |
| Growth | €349/mo | €299/mo | 12M | 50 members | Scale-ups, high traffic |
The free tier is generous by design: 500K requests/month is enough for an app with thousands of active users. The goal is to lower the entry barrier — if a developer tries Rollgate and it works, upgrading to Starter as the project grows is natural.
Why Not Open Source?
I evaluated the open-core model (free core, paid enterprise features), but it requires an active community to work. For a solo project, the risk is giving everything away for free without monetizing. I opted for a SaaS model with a generous free tier, with plans to release a self-hosted version under BSL (Business Source License) — the same approach used by HashiCorp and Sentry.
If you're looking for a LaunchDarkly alternative that doesn't cost as much as an employee, try Rollgate. It's free to get started.