Migration
Migrate from LaunchDarkly, Unleash, or Flagsmith to можно.. This guide covers flag export/import, API key migration, SDK replacement, and common pitfalls.
General Migration Strategy
graph LR
A[Export from Source] --> B[Transform Data]
B --> C[Import to Mozhno]
C --> D[Configure Environments]
D --> E[Switch SDK]
E --> F[Verify]
F --> G[Decommission Old Platform]
The Parallel-Run Approach
The safest migration runs both platforms in parallel during cutover:
- Week 1: Export flags from source, import into можно. Configure environments and API keys.
- Week 2: Integrate можно. SDK alongside existing SDK. Evaluate flags on both platforms. Compare results in logs.
- Week 3: Route 10% of traffic to можно. for flag decisions. Monitor for discrepancies.
- Week 4: Ramp to 100%. Remove old SDK. Decommission old platform.
LaunchDarkly → можно.
Conceptual Mapping
| LaunchDarkly | можно. |
|---|---|
| Project | Account (built-in, no explicit hierarchy) |
| Environment | Environment |
| Flag | Flag |
| Targeting Rule | Strategy |
| Segment | Segment |
| User / Context | Evaluation Context |
| SDK Key | API Key (per environment) |
| Mobile Key | Client-side API Key (read-only) |
Export from LaunchDarkly
LaunchDarkly does not provide a direct flag export in their UI. Use the REST API:
# Set your LD API token
LD_API_TOKEN="api-xxxxxxxx"
# Export all flags from a project/environment
curl -H "Authorization: ${LD_API_TOKEN}" \
"https://app.launchdarkly.com/api/v2/flags/<PROJECT_KEY>?env=<ENV_KEY>" \
| jq '.items' > ld_flags.jsonExport segments separately:
curl -H "Authorization: ${LD_API_TOKEN}" \
"https://app.launchdarkly.com/api/v2/segments/<PROJECT_KEY>/<ENV_KEY>" \
| jq '.items' > ld_segments.jsonTransform
LaunchDarkly uses a different flag evaluation model (server-side evaluation with streaming updates). можнo. uses local evaluation. Some LD features do not map directly:
| LD Feature | Migration Path |
|---|---|
| Custom targeting rules | Convert to можнo. strategies |
| Prerequisites (flag dependencies) | Not supported — restructure with custom strategies |
| Experiments | Not supported in Community Edition |
| Relay Proxy | Not needed — SDK fetches directly from server |
| Data Export (events) | Configure webhooks (Enterprise) or poll audit log |
Import to Mozhno
Use the REST API to create flags programmatically:
MOZHNO_URL="https://mozhno.example.com"
MOZHNO_TOKEN="<admin-jwt>"
jq -c '.[]' ld_flags.json | while read -r flag; do
KEY=$(echo "$flag" | jq -r '.key')
NAME=$(echo "$flag" | jq -r '.name')
DESC=$(echo "$flag" | jq -r '.description // ""')
curl -X POST "${MOZHNO_URL}/api/v1/flags" \
-H "Authorization: Bearer ${MOZHNO_TOKEN}" \
-H "Content-Type: application/json" \
-d "{
\"key\": \"${KEY}\",
\"name\": \"${NAME}\",
\"description\": \"${DESC}\",
\"flagType\": \"RELEASE\",
\"environmentId\": <env-id>
}"
doneAPI Key Migration
LaunchDarkly SDK keys are single-purpose (one per environment). In можнo., create API keys per environment through the dashboard or API:
curl -X POST "${MOZHNO_URL}/api/v1/api-keys" \
-H "Authorization: Bearer ${MOZHNO_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name": "Production SDK Key", "environmentId": <env-id>, "type": "SERVER"}'
# Response contains the key — save it immediately, it is not retrievable laterUnleash → можно.
Conceptual Mapping
| Unleash | можно. |
|---|---|
| Feature Toggle | Flag |
| Activation Strategy | Strategy |
| Segment | Segment |
| Context Field | Context Attribute |
| API Token | API Key (per environment) |
| Unleash Proxy | Not needed — SDK evaluates locally |
Export from Unleash
Unleash provides a state export endpoint:
UNLEASH_URL="https://unleash.example.com"
UNLEASH_TOKEN="<admin-token>"
curl -H "Authorization: ${UNLEASH_TOKEN}" \
"${UNLEASH_URL}/api/admin/state/export" \
| jq '.features' > unleash_features.jsonTransform — Strategy Mapping
Unleash's activation strategies map to можнo. strategies:
graph LR
U1["Unleash: default"] --> M1["можно.: boolean on/off"]
U2["Unleash: gradualRollout"] --> M2["можно.: percentage rollout"]
U3["Unleash: userWithId"] --> M3["можно.: user segment"]
U4["Unleash: flexibleRollout"] --> M4["можно.: segment + percentage"]
U5["Unleash: remoteAddress"] --> M5["можно.: custom strategy"]
| Unleash Strategy | Migration Approach |
|---|---|
default | Set flag to ON + no additional targeting |
gradualRollout | Create a percentage strategy |
userWithId | Create a segment with user IDs |
flexibleRollout | Segment + percentage strategy combined |
remoteAddress | Implement a custom strategy in можнo. |
Key Differences
- Unleash sends feature toggle definitions on every SDK poll (server-side evaluation). можнo. SDKs evaluate locally — the server sends rules, and the SDK decides.
- Unleash has no built-in A/B testing. можнo. Community Edition does not support multivariate flags either — flags are boolean (
RELEASE/KILLSWITCH). - Unleash uses string IDs. можнo. uses numeric IDs internally; string keys are the external identifier.
Flagsmith → можно.
Conceptual Mapping
| Flagsmith | можно. |
|---|---|
| Feature | Flag |
| Segment | Segment |
| Environment | Environment |
| Server-Side SDK Key | API Key (per environment) |
| Identities | Evaluation Context |
| Traits | Context Attributes |
Export from Flagsmith
Flagsmith supports environment export via API:
FS_URL="https://api.flagsmith.com/api/v1"
FS_TOKEN="<admin-token>"
curl -H "Authorization: Token ${FS_TOKEN}" \
"${FS_URL}/environments/<env-id>/featurestates/" \
> flagsmith_features.jsonSDK Switch Checklist
| Step | Flagsmith SDK | можнo. SDK |
|---|---|---|
| 1. Dependency | flagsmith-java-client | dev.mozhno:mozhno-client-java |
| 2. Init | FlagsmithClient.builder().withApiKey("...") | MozhnoConfig.builder().apiKey("...") + new DefaultMozhnoClient(config) |
| 3. Boolean flag | client.hasFeature("flag-key") | client.isEnabled("flag-key", context) |
| 4. String flag | client.getFeatureValue("flag-key") | Not supported — flags are boolean |
| 5. Context | FlagsmithUser / identity | MozhnoContext |
| 6. Poll interval | Configurable (default 60 s) | Configurable (default 15 s) |
SDK Switch Checklist (All Platforms)
Use this checklist regardless of source platform:
Java SDK
- Remove old SDK dependency (e.g.,
launchdarkly-java-server-sdk) - Add можнo. SDK:
implementation("dev.mozhno:mozhno-client-java:1.0.1") - Build client:
// Old (LaunchDarkly)
LDClient client = new LDClient("sdk-key-xxx");
// New (можно.)
MozhnoConfig config = MozhnoConfig.builder()
.appName("my-app")
.instanceId("instance-1")
.apiKey("mz_key_xxx")
.mozhnoUrl("https://mozhno.example.com")
.fetchTogglesInterval(30)
.build();
MozhnoClient client = new DefaultMozhnoClient(config);
client.start();- Replace flag evaluations:
// Old
boolean enabled = client.boolVariation("feature-x", user, false);
// New (можно.)
boolean enabled = client.isEnabled("feature-x",
MozhnoContext.builder()
.userId(user.getId())
.addProperty("email", user.getEmail())
.build(), false);- Update context building — можнo. uses a flat map of string attributes via
MozhnoContext. - Remove event tracking (LaunchDarkly
client.track()) — use audit log export or webhooks instead. - Shutdown hook:
client.stop()in a@PreDestroyor shutdown hook.
JavaScript SDK
- Remove old SDK dependency
- Add можнo. SDK:
npm install @mozhno/client-js - Build client:
// Old (LaunchDarkly)
const client = LDClient.initialize('sdk-key-xxx', user);
// New (можно.)
import { MozhnoClient } from '@mozhno/client-js';
const client = new MozhnoClient({
apiKey: 'mz_key_xxx',
url: 'https://mozhno.example.com',
appName: 'my-app',
refreshInterval: 30,
});
await client.start();- Replace flag evaluations:
// Old
const enabled = await client.variation('feature-x', false);
// New (можно.)
const enabled = client.isEnabled('feature-x', {
userId: user.id,
email: user.email,
});Common Pitfalls
1. Flag Key Naming
можнo. flag keys must be alphanumeric with hyphens and underscores. No dots, no slashes:
| Source | Valid in можнo.? |
|---|---|
feature.x (LD) | ❌ Dots not allowed |
feature-x | ✅ |
feature/x (FS) | ❌ Slashes not allowed |
feature_x | ✅ |
Fix: Rename keys during export. Update your code to match.
2. Environment Order
можнo. evaluates flags per environment. A flag can be ON in production but OFF in staging. Ensure your SDK is configured with the correct environment's API key — each API key is bound to a single environment.
3. Boolean Only
LaunchDarkly flags are always multivariate (they can return JSON). можнo. Community Edition flags are boolean only — either RELEASE (gradual rollout) or KILLSWITCH (instant disable). If you used an LD flag that returned a JSON variation, model it with application logic gated by a boolean flag.
4. User Targeting
можнo. evaluates flags against a MozhnoContext — a flat map of string keys to values. Nested LaunchDarkly custom attributes must be flattened:
// LaunchDarkly: nested attributes
user.custom("address", Map.of("country", "US", "city", "NYC"));
// можно.: flat attributes
MozhnoContext.builder()
.addProperty("country", "US")
.addProperty("city", "NYC")
.build();5. SDK Initialization Delay
During the first SDK poll (before the local cache is populated), flags return their default value. Ensure your code handles the uninitialized state gracefully:
// Default value is used until first sync completes
boolean enabled = client.isEnabled("new-feature", context);
// enabled == false (the default) until flags are loaded6. Percentage Rollout Precision
LaunchDarkly uses a hash-based algorithm on the user key for deterministic percentage rollout. можнo. uses a similar approach but the hash function differs. The same user may fall into a different bucket. When migrating a percentage rollout, start at 0% and ramp up gradually.
7. Webhooks
LaunchDarkly and Flagsmith have built-in webhooks for flag change events. можнo. Community Edition does not include webhooks. Use the audit log API to poll for changes, or use the Enterprise webhook SPI.
8. API Rate Limits
можнo. does not enforce hard rate limits by default, but the SDK polls every 15 seconds per instance. With 1000 SDK instances, that's ~66 requests/second — within the capacity of a single server. If you use the REST API directly for flag management, batch operations where possible.
Verification Checklist
Before decommissioning the old platform, verify:
- [ ] All flags exported and imported with correct keys and types
- [ ] Percentage rollouts migrated with equivalent percentages
- [ ] Segments recreated with equivalent targeting rules
- [ ] API keys generated for each environment
- [ ] SDK initializes without errors in all environments (dev, staging, production)
- [ ] Flag evaluations return expected values for 10+ test contexts
- [ ] All team members have access to the можнo. dashboard
- [ ] Audit trail is logging changes correctly
- [ ] Backups are configured (see Database)
Related Pages
- Architecture — How можнo. works internally
- Open Core — SPI and enterprise features
- Docker — Deployment