Migration TEST to LIVE
Guide to migrate your integration from TEST environment to PRODUCTION safely.
Overview
MONCRENEAU API provides 2 environments:
| Environment | Usage | Data |
|---|---|---|
| Staging | Development, staging | Test data, no real appointments |
| Production | Production | Real 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 "Authorization: Bearer $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
- Log in to your MONCRENEAU account
- Go to Settings > API > Production
- Click "Generate Production keys"
- 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
Recommended Structure
.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
- MONCRENEAU Dashboard > Webhooks > Production
- Enter your production URL:
https://your-app.com/webhooks/moncreneau - Copy webhook secret
- 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 "Authorization: Bearer $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 "Authorization: Bearer $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 "Authorization: Bearer $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
}