Skip to main content

Migration TEST to LIVE

Guide to migrate your integration from TEST environment to PRODUCTION safely.

Overview​

MONCRENEAU API provides 2 environments:

EnvironmentUsageData
StagingDevelopment, stagingTest data, no real appointments
ProductionProductionReal data, real appointments, consumes credits

⚠️ Important: Staging and Production keys are completely separate. Staging data does NOT migrate to Production.

Before Migration​

✅ Pre-Migration Checklist​

  • Complete tests passed locally
  • Webhooks tested and verified (HMAC signature)
  • Error handling implemented (retry, circuit breaker)
  • Monitoring configured (logs, metrics, alerts)
  • Internal documentation up to date
  • Team trained and ready
  • Rollback plan defined

Technical Verifications​


# 1. Verify tests pass
npm test

# 2. Check environment variables
env | grep MONCRENEAU

# 3. Test API connection
curl -H "X-API-Key: $MONCRENEAU_API_KEY" https://mc-prd.duckdns.org/api/v1/appointments

# 4. Verify webhooks work
# (create test appointment and verify reception)

Step 1: Obtain Production Keys​

Request Keys​

  1. Log in to your MONCRENEAU account
  2. Go to Settings > API > Production
  3. Click "Generate Production keys"
  4. Save immediately the keys in your secrets manager

Secure Keys​


# ❌ NEVER in code
const apiKey = "YOUR_API_KEY";

# ❌ NEVER in Git
MONCRENEAU_API_KEY=YOUR_API_KEY # In committed .env

# ✅ Server environment variables
# Heroku
heroku config:set MONCRENEAU_API_KEY=YOUR_API_KEY

# AWS Systems Manager
aws ssm put-parameter --name /prod/moncreneau/api_key --value "YOUR_API_KEY" --type SecureString

# Kubernetes Secret
kubectl create secret generic moncreneau-api --from-literal=api-key=YOUR_API_KEY

Step 2: Environment Configuration​

.env.development   # Development keys
.env.production # Production keys

Configuration Example​

// config/api.js
const environments = {
development: {
apiUrl: '{{API_BASE_URL}}',
apiKey: process.env.MONCRENEAU_API_KEY,
webhookSecret: process.env.MONCRENEAU_WEBHOOK_SECRET,
},
production: {
apiUrl: '{{API_BASE_URL}}',
apiKey: process.env.MONCRENEAU_API_KEY,
webhookSecret: process.env.MONCRENEAU_WEBHOOK_SECRET,
}
};

const env = process.env.NODE_ENV || 'development';
module.exports = environments[env];

Startup Validation​

// app.js
const config = require('./config/api');

function validateConfig() {
const required = ['apiUrl', 'apiKey', 'webhookSecret'];

for (const key of required) {
if (!config[key]) {
console.error(`❌ Missing config: ${key}`);
process.exit(1);
}
}

console.log('✓ Configuration validated');
console.log(`Environment: ${process.env.NODE_ENV}`);
console.log(`API URL: ${config.apiUrl}`);
console.log(`API Key: ${config.apiKey.substring(0, 15)}...`);
}

validateConfig();

Step 3: Production Webhook Configuration​

Obtain Production Webhook Secret​

  1. MONCRENEAU Dashboard > Webhooks > Production
  2. Enter your production URL: https://your-app.com/webhooks/moncreneau
  3. Copy webhook secret
  4. Save it in your environment variables

Verify Webhook URL​


# URL must be:
# ✅ HTTPS (valid SSL certificate)
# ✅ Publicly accessible (not localhost)
# ✅ Responds in < 5 seconds

# Manual test
curl -X POST https://your-app.com/webhooks/moncreneau -H "Content-Type: application/json" -H "X-Moncreneau-Signature: sha256=test" -d '{"id":"evt_test","type":"appointment.created"}'

# Should return 401 (invalid signature) or 200

Step 4: Progressive Deployment​

Blue-Green Strategy​


# 1. Deploy new version (green) with Production keys
# But without routing traffic

# 2. Test green version
curl https://green.your-app.com/health

# 3. Create production test appointment
curl -X POST https://green.your-app.com/api/appointments -H "X-API-Key: $MONCRENEAU_API_KEY" -d '{ ... }'

# 4. Verify webhook arrives
# Check logs: "Webhook received: appointment.created"

# 5. If OK, route traffic to green
# 6. Monitor metrics for 1h
# 7. If OK, remove blue

Feature Flags​

const FeatureFlags = {
USE_PROD_API: process.env.FEATURE_USE_PROD_API === 'true'
};

function getApiConfig() {
return {
apiUrl: '{{API_BASE_URL}}',
apiKey: process.env.MONCRENEAU_API_KEY
};
}

Step 5: Post-Migration Verifications​

Production Tests​


# 1. Create test appointment
curl -X POST https://mc-prd.duckdns.org/api/v1/appointments -H "X-API-Key: $MONCRENEAU_API_KEY" -H "Content-Type: application/json" -d '{
"departmentId": 5,
"dateTime": "2026-02-15T10:00:00",
"name": "Test Migration"
}'

# 2. Check MONCRENEAU dashboard
# Appointment must appear

# 3. Verify webhook arrived
# Logs: "Webhook appointment.created received"

# 4. Cancel test appointment
curl -X DELETE https://mc-prd.duckdns.org/api/v1/appointments/{id} -H "X-API-Key: $MONCRENEAU_API_KEY"

# 5. Verify appointment.cancelled webhook

Enhanced Initial Monitoring​

// More aggressive alerts first days
const alertThresholds = {
production_first_week: {
errorRate: 0.01, // 1% (vs 5% normal)
responseTime: 200, // 200ms (vs 500ms normal)
webhookDelay: 5 // 5s (vs 60s normal)
}
};

// Temporary detailed logs
if (isFirstWeekInProduction()) {
logger.level = 'debug';
logger.info('Running in first week mode - enhanced logging');
}

Step 6: Credits Management​

Check Balance​

async function checkCreditsBeforeLaunch() {
const response = await api.get('/organizations/me');
const credits = response.data.availableCredits;

console.log(`Available credits: ${credits}`);

if (credits < 100) {
console.warn('⚠️ Low credits! Consider purchasing more.');
}

return credits;
}

Credit Alerts​

// Monitor credit balance
setInterval(async () => {
const org = await api.get('/organizations/me');
const credits = org.data.availableCredits;

if (credits < 50) {
await sendAlert('ALERT: Only ' + credits + ' credits left!');
} else if (credits < 100) {
await sendAlert('WARNING: Less than 100 credits remaining');
}
}, 3600000); // Every hour

Rollback​

Quick Rollback Plan​


# 1. If critical issue detected
# 2. Immediately revert to previous version

# Heroku
heroku releases:rollback

# Kubernetes
kubectl rollout undo deployment/your-app

# Docker
docker-compose down
docker-compose -f docker-compose.old.yml up -d

# 3. Restore previous keys if needed
heroku config:set MONCRENEAU_API_KEY=$PREVIOUS_API_KEY

# 4. Verify app works
curl https://your-app.com/health

Rollback Criteria​

Trigger rollback if:

  • ❌ Error rate > 10% for 5 minutes
  • ❌ Response time > 2 seconds
  • ❌ No webhooks received for 10 minutes
  • ❌ Credits consumed abnormally fast
  • ❌ More than 5 user error reports

Migration Checklist​

Before Deployment​

  • All tests pass locally
  • Production keys obtained and secured
  • Production environment variables configured
  • Production webhook URL configured and tested
  • Monitoring and alerts enabled
  • Team notified (date and time)
  • Rollback plan documented
  • Current data backed up

During Deployment​

  • Deployment during off-peak hours
  • Real-time monitoring active
  • Team available (dev + ops)
  • User communication sent
  • First test appointment created
  • Test webhook received and processed
  • Normal metrics (errors, latency)

After Deployment​

  • Enhanced monitoring for 24h
  • No critical errors detected
  • Webhooks received correctly
  • Credits consumed normally
  • Users satisfied (no complaints)
  • Documentation updated
  • Post-mortem if incidents
  • Previous keys archived (not deleted)

Communication​

User Announcement​

📢 Scheduled Maintenance

Date: Saturday, February 10, 2024
Time: 02:00 - 04:00 GMT
Duration: Approximately 30 minutes

During this period, our appointment system will be
temporarily unavailable. Existing appointments are
not affected.

Thank you for your understanding!

Success Notification​

✅ Migration Complete

Our appointment system has been successfully migrated
to our production infrastructure. You can continue
using the service normally.

If you encounter any issues, please contact us
immediately.

Troubleshooting​

Error: "Invalid API Key"​

// Check environment
console.log('NODE_ENV:', process.env.NODE_ENV);
console.log('API Key:', process.env.MONCRENEAU_API_KEY?.substring(0, 10));

// Verify key starts with live_
if (!process.env.MONCRENEAU_API_KEY?.startsWith('live_')) {
console.error('❌ Using TEST key in production!');
}

Webhooks Not Received​

# 1. Check configured URL
# Dashboard > Webhooks > Production > URL

# 2. Test manually
curl -X POST https://your-app.com/webhooks/moncreneau \
-d '{"id":"evt_test","type":"appointment.created"}'

# 3. Check server logs
tail -f /var/log/app.log | grep webhook

# 4. Check firewall
# MONCRENEAU IP must be allowed

Credits Consumed Too Fast​

// Audit appointment creations
const recentAppointments = await db.appointments.find({
createdAt: { $gte: new Date(Date.now() - 3600000) } // 1h
});

console.log(`${recentAppointments.length} appointments in last hour`);

// If abnormal, temporarily suspend
if (recentAppointments.length > 100) {
console.error('⚠️ Abnormal appointment rate!');
// Trigger alert
// Potentially disable creation temporarily
}

Resources​