OpenFeature-native feature flag management platform for controlled releases, A/B testing, and experimentation.
Claim your free access at GitHub Education Pack - look for DevCycle.
- Main Dashboard: https://app.devcycle.com
- Environments: https://app.devcycle.com/r/environments
- API Keys: Project Settings → Environments → SDK Keys
- Feature Flags: Toggle features without deployment
- Gradual Rollouts: Release to percentage of users
- A/B Testing: Experiment with variations
- Targeting: Rules based on user properties
- OpenFeature Native: No vendor lock-in
- 15+ SDKs: Web, mobile, backend
npm install @devcycle/nodejs-server-sdkimport { initializeDevCycle } from '@devcycle/nodejs-server-sdk';
const devcycleClient = await initializeDevCycle(
process.env.DEVCYCLE_SERVER_SDK_KEY
);
const user = { user_id: 'user-123' };
const showNewFeature = await devcycleClient.variableValue(
user,
'new-feature-flag',
false
);
if (showNewFeature) {
// Show new feature
}npm install @devcycle/react-client-sdkimport { DevCycleProvider, useVariableValue } from '@devcycle/react-client-sdk';
function App() {
return (
<DevCycleProvider
sdkKey={process.env.REACT_APP_DEVCYCLE_CLIENT_SDK_KEY}
user={{ user_id: 'user-123' }}
>
<MyComponent />
</DevCycleProvider>
);
}
function MyComponent() {
const showFeature = useVariableValue('new-feature', false);
return showFeature ? <NewFeature /> : <OldFeature />;
}pip install devcycle-python-server-sdkfrom devcycle_python_sdk import DevCycleLocalClient, DevCycleLocalOptions
options = DevCycleLocalOptions()
client = DevCycleLocalClient(os.environ.get("DEVCYCLE_SERVER_SDK_KEY"), options)
user = {"user_id": "user-123"}
show_feature = client.variable_value(user, "new-feature", False)Copy from templates/devcycle/:
devcycle.config.js- SDK configuration.env.example- Environment variables
DEVCYCLE_SERVER_SDK_KEY=server-key-here
# Get from: https://app.devcycle.com → Project → Environments → Server SDK Key
DEVCYCLE_CLIENT_SDK_KEY=client-key-here
# Get from: https://app.devcycle.com → Project → Environments → Client SDK Keyconst enabled = await client.variableValue(user, 'feature-enabled', false);const theme = await client.variableValue(user, 'ui-theme', 'light');
// Returns: 'light', 'dark', 'auto'const config = await client.variableValue(user, 'feature-config', {});
// Returns: { maxItems: 10, showBanner: true }const user = {
user_id: 'user-123',
email: 'user@example.com',
customData: {
plan: 'premium',
country: 'US'
}
};
// Target users where plan = 'premium'- 10% → Test with small group
- 50% → Broader beta
- 100% → Full release
# .github/workflows/devcycle-sync.yml
name: DevCycle Sync
on:
push:
branches: [main]
jobs:
sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: DevCycle Code References
uses: DevCycleHQ/feature-flag-code-refs@v1
with:
client-id: ${{ secrets.DEVCYCLE_CLIENT_ID }}
client-secret: ${{ secrets.DEVCYCLE_CLIENT_SECRET }}
project: your-project-key- Use descriptive names:
show-new-checkoutnotflag-1 - Set defaults: Always provide fallback values
- Clean up old flags: Remove after full rollout
- Test variations: Verify all flag states work
- Use targeting: Roll out to internal users first
import { OpenFeature } from '@openfeature/js-sdk';
import { DevCycleProvider } from '@devcycle/openfeature-web-provider';
OpenFeature.setProvider(new DevCycleProvider(sdkKey));
const client = OpenFeature.getClient();
const showFeature = await client.getBooleanValue('new-feature', false);