Subchapter 22.5
references/multi-language-setup.mdMarkdown11 KBView on GitHub
Guidance for polyglot architectures with multiple languages/frameworks.
In a microservices or polyglot architecture, you may have services in different languages that need to share LaunchDarkly projects or maintain separate projects per service.
One project, different services consume from different environments or contexts.
When to use:
Project: "my-app"
├── Service A (Python) → Uses "my-app" production SDK key
├── Service B (Node.js) → Uses "my-app" production SDK key
└── Service C (Go) → Uses "my-app" production SDK keyEach service has its own project.
When to use:
Project: "service-a" → Service A (Python)
Project: "service-b" → Service B (Node.js)
Project: "service-c" → Service C (Go)Shared projects for related services, separate for others.
Project: "frontend-services"
├── Web App (React)
└── Mobile App (React Native)
Project: "backend-services"
├── API Gateway (Node.js)
└── Auth Service (Go)
Project: "ml-services"
├── Recommendation Engine (Python)
└── Model Serving (Python)Create a central service for project management that other services can use:
# project-manager-service/app.py
from flask import Flask, jsonify, request
from launchdarkly.projects import ProjectManager
app = Flask(__name__)
pm = ProjectManager()
@app.route('/projects', methods=['POST'])
def create_project():
"""Central API to create projects for any service."""
data = request.json
project = pm.create_project(
name=data['name'],
key=data['key'],
tags=data.get('tags', [])
)
return jsonify(project)
@app.route('/projects/<key>/keys/<env>')
def get_sdk_key(key, env):
"""Get SDK key for any service."""
sdk_key = pm.get_sdk_key(key, env)
return jsonify({'sdkKey': sdk_key})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)Each service calls the central API:
Python Service:
import requests
def get_launchdarkly_sdk_key():
resp = requests.get(
'http://project-manager:8080/projects/my-service/keys/production'
)
return resp.json()['sdkKey']Node.js Service:
async function getLaunchDarklySdkKey(): Promise<string> {
const resp = await fetch(
'http://project-manager:8080/projects/my-service/keys/production'
);
const data = await resp.json();
return data.sdkKey;
}Go Service:
func getLaunchDarklySdkKey() (string, error) {
resp, err := http.Get("http://project-manager:8080/projects/my-service/keys/production")
if err != nil {
return "", err
}
defer resp.Body.Close()
var result struct {
SdkKey string `json:"sdkKey"`
}
json.NewDecoder(resp.Body).Decode(&result)
return result.SdkKey, nil
}Maintain a central config repo that all services reference:
config-repo/
├── launchdarkly/
│ ├── projects.yaml # Project definitions
│ ├── sdk-keys/
│ │ ├── production/
│ │ │ ├── service-a.key
│ │ │ ├── service-b.key
│ │ │ └── service-c.key
│ │ └── test/
│ │ ├── service-a.key
│ │ ├── service-b.key
│ │ └── service-c.key
│ └── scripts/
│ ├── create_projects.py
│ └── sync_keys.shprojects.yaml:
projects:
- name: Service A
key: service-a
tags: [python, backend]
services:
- name: service-a
language: python
- name: Service B
key: service-b
tags: [nodejs, api]
services:
- name: service-b
language: nodejs
- name: Service C
key: service-c
tags: [go, gateway]
services:
- name: service-c
language: goSync script:
#!/bin/bash
# scripts/sync_keys.sh
for env in production test; do
for service in service-a service-b service-c; do
sdk_key=$(python scripts/get_sdk_key.py $service $env)
echo "$sdk_key" > "sdk-keys/$env/$service.key"
echo "✓ Synced $service/$env"
done
doneCreate templates for each language:
# templates/python/launchdarkly_setup.py
import os
from launchdarkly.projects import ProjectManager
def setup_project(service_name: str):
"""Setup LaunchDarkly project for Python service."""
pm = ProjectManager()
project = pm.create_project(
name=f"{service_name} Service",
key=service_name,
tags=["python", "service"]
)
sdk_key = pm.get_sdk_key(service_name, "production")
# Save to .env
with open(".env", "w") as f:
f.write(f"LAUNCHDARKLY_SDK_KEY={sdk_key}\n")
print(f"✓ Setup complete for {service_name}")// templates/nodejs/launchdarkly-setup.ts
import { ProjectManager } from './launchdarkly/projects';
import * as fs from 'fs';
async function setupProject(serviceName: string): Promise<void> {
const pm = new ProjectManager();
const project = await pm.createProject({
name: `${serviceName} Service`,
key: serviceName,
tags: ['nodejs', 'service'],
});
const sdkKey = await pm.getSdkKey(serviceName, 'production');
// Save to .env
fs.writeFileSync('.env', `LAUNCHDARKLY_SDK_KEY=${sdkKey}\n`);
console.log(`✓ Setup complete for ${serviceName}`);
}// templates/go/launchdarkly_setup.go
package main
import (
"fmt"
"os"
"yourmodule/pkg/launchdarkly"
)
func setupProject(serviceName string) error {
pm := launchdarkly.NewProjectManager("")
project, err := pm.CreateProject(
fmt.Sprintf("%s Service", serviceName),
serviceName,
[]string{"go", "service"},
)
if err != nil {
return err
}
sdkKey, err := pm.GetSDKKey(serviceName, "production")
if err != nil {
return err
}
// Save to .env
f, err := os.Create(".env")
if err != nil {
return err
}
defer f.Close()
fmt.Fprintf(f, "LAUNCHDARKLY_SDK_KEY=%s\n", sdkKey)
fmt.Printf("✓ Setup complete for %s\n", serviceName)
return nil
}For monorepos with multiple services:
monorepo/
├── services/
│ ├── api/ (Node.js)
│ ├── worker/ (Python)
│ └── gateway/ (Go)
├── packages/
│ └── launchdarkly-setup/
│ ├── python/
│ │ └── setup.py
│ ├── nodejs/
│ │ └── setup.ts
│ └── go/
│ └── setup.go
└── scripts/
└── setup-all-projects.shsetup-all-projects.sh:
#!/bin/bash
echo "Setting up LaunchDarkly projects for all services..."
cd services/api
npm run setup-launchdarkly
cd ../worker
python scripts/setup_launchdarkly.py
cd ../gateway
go run scripts/setup_launchdarkly.go
echo "✓ All services configured"Standardize environment variable names across languages:
# Common convention
LAUNCHDARKLY_SDK_KEY=<production-key>
LAUNCHDARKLY_SDK_KEY_TEST=<test-key>
LAUNCHDARKLY_PROJECT_KEY=<project-key>
LAUNCHDARKLY_ENVIRONMENT=<production|test>Loading in each language:
Python:
import os
sdk_key = os.environ['LAUNCHDARKLY_SDK_KEY']Node.js:
const sdkKey = process.env.LAUNCHDARKLY_SDK_KEY;Go:
sdkKey := os.Getenv("LAUNCHDARKLY_SDK_KEY")Ruby:
sdk_key = ENV['LAUNCHDARKLY_SDK_KEY']Java:
String sdkKey = System.getenv("LAUNCHDARKLY_SDK_KEY");Share SDK keys via Kubernetes ConfigMap:
# k8s/launchdarkly-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: launchdarkly-config
data:
project-key: "my-app"
environment: "production"
---
apiVersion: v1
kind: Secret
metadata:
name: launchdarkly-secrets
type: Opaque
stringData:
sdk-key: "sdk-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"Mount in all services:
apiVersion: apps/v1
kind: Deployment
metadata:
name: service-a
spec:
template:
spec:
containers:
- name: app
env:
- name: LAUNCHDARKLY_SDK_KEY
valueFrom:
secretKeyRef:
name: launchdarkly-secrets
key: sdk-key
- name: LAUNCHDARKLY_PROJECT_KEY
valueFrom:
configMapKeyRef:
name: launchdarkly-config
key: project-keyFor service mesh (Istio, Linkerd), use a sidecar pattern:
# Sidecar that manages LaunchDarkly SDK keys
apiVersion: v1
kind: Pod
metadata:
name: my-service
spec:
containers:
# Main application
- name: app
image: my-service:latest
env:
- name: LAUNCHDARKLY_SDK_KEY
value: /var/run/secrets/launchdarkly/sdk-key
volumeMounts:
- name: ld-keys
mountPath: /var/run/secrets/launchdarkly
# Sidecar that fetches/refreshes keys
- name: ld-key-sync
image: ld-key-sync:latest
env:
- name: LAUNCHDARKLY_API_TOKEN
valueFrom:
secretKeyRef:
name: ld-api-token
key: token
- name: PROJECT_KEY
value: my-service
volumeMounts:
- name: ld-keys
mountPath: /var/run/secrets/launchdarkly
volumes:
- name: ld-keys
emptyDir: {}Project Key Format: {service-name}-{optional-suffix}
Examples:
- api-gateway
- user-service
- recommendation-enginetags = [
"language:python", # or nodejs, go, etc.
"team:platform", # owning team
"environment:prod", # deployment env
"type:service" # or frontend, worker, etc.
]Maintain a service registry:
# Service Registry
| Service | Language | Project Key | Team | Status |
|---------|----------|-------------|------|--------|
| API Gateway | Node.js | api-gateway | Platform | Active |
| User Service | Go | user-service | Identity | Active |
| ML Engine | Python | ml-engine | Data Science | Active |Automate project creation for new services:
# scripts/new-service.sh
#!/bin/bash
SERVICE_NAME=$1
LANGUAGE=$2
# Create project
python scripts/create_project.py \
--name "$SERVICE_NAME Service" \
--key "$SERVICE_NAME" \
--tags "language:$LANGUAGE,type:service"
# Generate template
cp -r "templates/$LANGUAGE" "services/$SERVICE_NAME"
# Setup SDK key
cd "services/$SERVICE_NAME"
bash setup.sh
echo "✓ New service $SERVICE_NAME created"