Feature flags for dev teams
Ship dark.Reveal onyour terms.
Simple, fast feature flags with predictable pricing. Flags are evaluated inside your process, so a toggle costs you microseconds, not a network hop.
- Local evaluation
- Fail-static by design
- Flat plans, no overage
const on = await client.boolean(
'new-checkout', { key: userId }, false
); Simple
Six flag types, one rule model.
Boolean to JSON, targeted by the same conditions and segments.
Fast
Decided in your process.
The SDK holds the ruleset in memory. No request sits on your hot path.
Predictable
Flat plans. No overage.
Not per seat, not per user, not per evaluation. You know the invoice in advance.
01 Hybrid evaluation
The decision happens next to your code.
Server SDKs download a versioned ruleset and evaluate locally. They revalidate cheaply with ETags, and they keep serving if we cannot be reached.
Console & API
Edit a flag. We build a complete snapshot of the environment’s rules.
Ruleset CDN
Versioned snapshot served with an ETag.
SDK · local eval
In-memory rules. Decisions never leave the process.
Zero network on the hot path
Rules, segments and rollouts run in-process. Percentage buckets are deterministic, so a user lands in the same variation on every SDK.
A 304 is nearly free
SDKs poll with If-None-Match. Unchanged rulesets return no body; changed ones swap in atomically.
Down for us is not down for you
If the control plane is unreachable the SDK keeps the last good ruleset. Try the outage button above.
02 Flag types
More than on and off.
Kill switches, dark launches, gradual rollouts.
const on = await client.boolean('new-checkout', ctx, false); Copy tests, plan labels, remote strings without a deploy.
const copy = await client.string('banner-copy', ctx, ''); Limits, batch sizes, retry counts.
const mb = await client.int('max-upload-mb', ctx, 10); Weights, thresholds, sampling rates.
const boost = await client.float('search-boost', ctx, 1.0); Structured config. Invalid variations are rejected at save time.
const cfg = await client.json('pricing-table-config', ctx, {}); Launch windows and sunset dates that ops can change.
const ends = await client.date('promo-ends-at', ctx, null); 03 Targeting & rollouts
Lists and rules are read top to bottom.
First match wins, otherwise the default. Try an email in any casing, or a group, and watch the lists react. This is the same logic the SDK runs.
target list: email is one of [ana@acme.com, bo@acme.com]no matchtarget list: groups has any of [beta-testers, acme-staff]no matchplan equals "business"no matchcountry in [BR, PT] and in_segment beta-testersno matchrollout by key no match04 Privacy
We never store your users’ context.
Who your users are is evaluated in your process. What we keep are anonymous counters, so we can bill you and show usage.
Stays in your process
user.keyu_8841user.emailana@acme.comcountryBRplanprocustom attributes…
Reaches darkship
flag_keynew-checkoutvariationoncount / hour12,480sdk_versionjs-0.9.1
Details in the privacy policy and the telemetry post. LGPD and GDPR-style rights are supported.
05 SDKs
Three lines to your first flag.
import { createClient } from '@darkship/sdk';
const client = await createClient({ sdkKey: process.env.DARKSHIP_KEY });
const on = await client.boolean('new-checkout', { key: user.id, plan: user.plan }, false); from darkship import Client
client = Client(sdk_key=os.environ["DARKSHIP_KEY"])
on = client.boolean("new-checkout", {"key": user.id, "plan": user.plan}, False) import { OpenFeature } from '@openfeature/server-sdk';
import { DarkshipServerProvider } from '@darkship/openfeature-provider/server';
await OpenFeature.setProviderAndWait(new DarkshipServerProvider({ sdkKey }));
const on = await OpenFeature.getClient().getBooleanValue('new-checkout', false, ctx); 06 Pricing
Flat plans. No overage.
Priced by what you use, not by who is using it. Compare plans in detail.
Illustrative prices (USD). Final numbers must match the Stripe products before launch.
07 FAQ
Straight answers.
Your app keeps working. Server SDKs hold the last good ruleset in memory and keep evaluating locally (fail-static). Billing or quota problems never switch your flags off either: we fail open.
No. Evaluation context (user id, email, country, plan, custom attributes) is evaluated inside your process by the server SDK. For client SDKs the context is processed in memory for the single evaluation and discarded. We only keep aggregate counters.
A server SDK ruleset fetch (a 304 revalidation counts) or a client SDK remote evaluation. Evaluations inside a server SDK are local and free. See the pricing page for the full list.
No. Plans are flat. There is no per-seat, per-MAU or per-evaluation surprise; if you approach your quota we warn you early and never cut off your flags.
Yes. We ship an OpenFeature provider, so application code can use the vendor-neutral API and switch providers by changing one line.
Not in the current scope. The product is a hosted service; the SDKs and the REST API are documented so you can inspect what leaves your servers.
Ship dark. Reveal on your terms.
Create a project in a minute. The Free plan needs no card.