Request metadata
Coordinate releases across services using request metadata passed in API calls, headers, or RPC messages. This strategy enables version management and backward compatibility without requiring consumers to use LaunchDarkly.
Overview
Request metadata allows API providers to make targeting decisions based on information passed in requests. This enables coordinated releases with external consumers and loosely coupled services without requiring all participants to integrate with LaunchDarkly.
When to use request metadata
Use request metadata when:
- Services communicate via APIs, HTTP, or RPC
- API consumers do not use LaunchDarkly
- Services are in separate LaunchDarkly projects
- Services need to maintain backward compatibility
- Services have external or third-party consumers
How request metadata works
Each coordination strategy has two parts:
Platform
What teams do in LaunchDarkly: Create targeting rules based on API versions or client metadata to coordinate releases with external consumers.
Application
What developers implement:
Consumers attach metadata to requests through:
- HTTP headers
- Query parameters
- Request body fields
- RPC metadata
Providers use the metadata to define LaunchDarkly contexts for evaluation and targeting.
Request metadata scope
Request metadata works across boundaries:
| Architecture | Supported |
|---|---|
| Within a single project | Yes |
| Across multiple projects | Yes |
| Outside of projects | Yes |
Only the providing service needs to use LaunchDarkly. Consumers do not require LaunchDarkly integration.
Use cases
API version management
Manage breaking changes in public APIs by targeting based on API version.
Example scenario:
API service introduces breaking change to use UUID identifiers instead of integer IDs.
Setup:
- API consumers include version in header:
X-API-Version: 2.0.0 - API service extracts version and creates context:
const context = { kind: 'request', key: requestId, apiVersion: req.headers['x-api-version'] }; - Create targeting rule:
If apiVersion >= 2.0.0 then serve Available
Result:
Newer API clients automatically receive the new identifier format. Legacy clients continue using integer IDs until they upgrade.
Client-specific feature rollouts
Target features to specific mobile app versions or web browser versions.
Example scenario:
Mobile app releases new offline mode that requires minimum app version 3.5.0.
Setup:
- Mobile app includes version in API calls
- Backend service creates context with app version
- Create targeting rule:
If appVersion >= 3.5.0 then serve Available
Result:
Backend enables offline sync features only for app versions that support offline mode.
Tenant-specific releases
Enable features for specific tenants in multi-tenant services.
Example scenario:
SaaS application wants to roll out advanced analytics to premium tier customers.
Setup:
- API gateway includes tenant information in header:
X-Tenant-Id: acme-corp - Backend service extracts tenant and subscription tier
- Create targeting rule:
If subscriptionTier equals "premium" then serve Available
Result:
Premium tier customers see advanced analytics. Standard tier customers do not see the feature.
Implementation steps
Step 1: Define metadata schema
Determine what metadata consumers should provide:
- API version
- Client version
- Client type (web, mobile, desktop)
- Tenant identifier
- User tier or subscription level
Step 2: Update API consumers
Instruct consumers to include metadata in requests:
HTTP headers:
X-API-Version: 2.1.0
X-Client-Type: mobile-ios
X-Client-Version: 3.5.2
Query parameters:
GET /api/widgets?api_version=2.1.0&client=mobile-ios
Request body:
{
"data": { ... },
"metadata": {
"apiVersion": "2.1.0",
"clientType": "mobile-ios"
}
}
Step 3: Extract metadata in provider
Extract metadata from requests and create LaunchDarkly contexts:
Node.js example:
const express = require('express');
const { init } = require('@launchdarkly/node-server-sdk');
const app = express();
const ldClient = init(process.env.LD_SDK_KEY);
app.get('/api/widgets', async (req, res) => {
// Extract metadata from request
const apiVersion = req.headers['x-api-version'] || '1.0.0';
const clientType = req.headers['x-client-type'] || 'unknown';
// Create context for flag evaluation
const context = {
kind: 'request',
key: req.requestId,
apiVersion: apiVersion,
clientType: clientType
};
// Evaluate feature flag
const useNewFormat = await ldClient.variation(
'use-new-response-format',
context,
false
);
// Return appropriate response
if (useNewFormat) {
res.json({ data: getNewFormatData() });
} else {
res.json({ data: getLegacyFormatData() });
}
});
Step 4: Create targeting rules
Create targeting rules based on the extracted metadata:
- Navigate to the feature flag in LaunchDarkly
- Select the environment
- Create a new targeting rule
- Use the context attribute (for example, apiVersion)
- Configure the targeting logic (for example,
apiVersion >= 2.0.0) - Set the variation to serve
- Save the targeting rule
Step 5: Monitor and deprecate
Track usage of old API versions using flag evaluation metrics:
- Monitor which variations are being served
- Identify clients still using old versions
- Communicate deprecation timeline to affected clients
- Remove backward compatibility code when safe
Example configuration
Scenario: GraphQL API versioning
Context schema:
{
"kind": "api-consumer",
"key": "consumer-xyz",
"apiVersion": "2023-11-01",
"consumerType": "mobile-app",
"consumerVersion": "4.2.0"
}
Targeting rules:
Flag: use-new-schema
Rule 1: Early access beta testers
If consumerType equals "internal" then serve Available
Rule 2: New API version
If apiVersion >= "2023-11-01" then serve Available
Rule 3: Opt-in consumers
If consumer is one of ["consumer-abc", "consumer-xyz"] then serve Available
Default: Unavailable
Result:
- Internal testers always get the new schema
- Consumers using API version 2023-11-01 or later get the new schema
- Specific consumers can opt in to the new schema early
- All other consumers get the legacy schema
Best practices
Use semantic versioning
Use semantic versioning for API versions to enable meaningful comparisons:
- Major version: Breaking changes
- Minor version: Backward-compatible features
- Patch version: Backward-compatible fixes
Document metadata requirements
Provide clear documentation for API consumers:
- Required and optional metadata fields
- Format and valid values
- How metadata affects feature availability
- Deprecation timelines
Provide defaults
Handle missing or invalid metadata gracefully:
const apiVersion = req.headers['x-api-version'] || '1.0.0';
const parsed = parseVersion(apiVersion) || { major: 1, minor: 0, patch: 0 };
Use flag statuses
Track deprecated API versions with flag statuses. Monitor usage to determine when old versions can be safely removed.
To learn more, read Flag statuses.
Communicate deprecation timelines
Provide advance notice to API consumers:
- Include deprecation headers in API responses
- Send notifications to registered consumers
- Provide migration guides
- Offer support during the transition
Example deprecation header:
Deprecation: version="1.0", date="2024-06-01"
Sunset: date="2024-12-01"
Link: <https://api.example.com/docs/migration-guide>; rel="deprecation"
Test with multiple client versions
Verify targeting rules work correctly for all supported client versions:
- Test with minimum supported version
- Test with latest version
- Test with versions at version boundaries
- Test with missing or invalid metadata
Troubleshooting
All clients receiving the same variation
Symptom: Targeting rules based on metadata do not differentiate between clients.
Possible causes:
- Metadata not being extracted from requests
- Context not being created with the correct attributes
- Targeting rules using incorrect attribute names
Solution:
- Log extracted metadata to verify it is present
- Verify context creation includes the expected attributes
- Check targeting rule attribute names match context attribute names
Legacy clients breaking after rollout
Symptom: Clients using old API versions receive errors or unexpected behavior.
Possible causes:
- Default variation serves new behavior
- Targeting rule comparison logic is incorrect
- Missing fallback handling for old versions
Solution:
- Ensure default variation serves legacy behavior
- Verify version comparison logic (for example,
>=vs>) - Add explicit targeting rules for old versions if needed
Related strategies
Combine request metadata with other coordination strategies:
- Delegated authority: Grant API consumers permission to request custom targeting rules
- Prerequisite flags: Use prerequisites for internal coordination while using request metadata for external coordination
To learn more about context attributes, read Contexts.