Skip to content

Introduction

Featly is an open-source feature-management platform for .NET. It combines feature flags, dynamic configuration, segments, experiments, custom RBAC, and approval workflows into a single product that can be embedded inside your ASP.NET Core process (like Hangfire) or hosted centrally for many consumers.

This page is the five-minute mental model. Follow Getting started to run it, or jump to the Dashboard tour to see it.

Everything in Featly follows from a handful of decisions:

  • Local-first evaluation. The SDK evaluates flags and configs locally against a cached, fresh-by-default snapshot. There is no network call on the hot path; a boolean flag resolves in tens of nanoseconds.
  • Embedded like Hangfire. The server, dashboard, and SDK can all run inside the consumer’s process. Two DI calls plus a middleware mount and you are operational.
  • The same engine everywhere. Featly.Engine evaluates flags identically in the SDK and on the server — consistency by construction.
  • Resilient by default. The SDK serves last-known-good config if the server is unreachable, and can bootstrap from a static JSON file.
  • Storage is an interface. All persistence goes through IFeatlyStore. SQLite ships in the box; other providers are pluggable.
  • DB beats config. Runtime-editable settings have three-layer precedence: hardcoded default → appsettings.json → database.

A flag is a named decision. Boolean flags answer yes/no; multivariate flags return one of several typed variants (string, int, double, JSON). Flags carry targeting rules that decide which variant a given context receives.

A config is a typed value (string, int, decimal, JSON, …) resolved through the same targeting engine as flags. Use it for values that change without a deploy — timeouts, limits, copy, feature parameters.

A flag or config has an ordered list of rules. Each rule is a set of AND-ed conditions (attribute, operator, value) that resolve to a variant or a weighted split. The first matching rule wins; if none match, the default variant is served. Splits bucket deterministically, so the same targeting key always lands in the same bucket.

A segment is a named, reusable audience definition (a set of conditions). A rule can target a segment by reference, so “beta users” is defined once and used across many flags.

An experiment is an A/B test built on flags: deterministic bucketing plus exposure events, so you can measure the effect of a variant.

A project isolates one application’s flags. An environment (development, staging, production, …) is a deployment target with its own values and its own governance. API keys are scoped to an environment.

Featly is built for teams who need control:

  • Custom RBAC — four immutable system roles (Viewer, Editor, Approver, Admin) plus user-defined roles, with ~45 granular permissions.
  • Approval workflows — protected environments turn mutations into pending changes that require review before they apply.
  • Audit log — every mutation, approval, and settings change is recorded with a before/after diff.
  • ReadOnly environment lock — freeze an environment during an incident.
  • Dry-run — preview the effect of any mutation without applying it.
Your ASP.NET Core app
┌─────────────────────────────────────────────┐
│ Featly.Server ── admin + SDK HTTP APIs │
│ Featly.Dashboard ── embedded UI at /featly │
│ Featly.Engine ── evaluation (shared) │
│ IFeatlyStore ── SQLite / your database │
└─────────────────────────────────────────────┘
▲ ▲
│ HTTP (sync snapshot) │ local evaluation
│ │
┌────────┴────────┐ ┌────────┴────────────┐
│ Featly.Sdk │ │ same process (opt.) │
│ (other services)│ │ │
└─────────────────┘ └─────────────────────┘

Read on: