Production Deployment Checklist
Use this checklist to ensure your LinkForty deployment is production-ready, secure, and reliable.
This checklist primarily applies to self-hosted LinkForty Core deployments. If you're using LinkForty Cloud, infrastructure, security, backups, and monitoring are handled for you - see the Quick Start to get started.
Pre-Deployment Planning
Infrastructure Requirements
-
Server sizing - Provision appropriate resources
- Minimum: 2 CPU cores, 4 GB RAM, 20 GB SSD
- Recommended: 4 CPU cores, 8 GB RAM, 100 GB SSD
- See Self-Hosting Guide for provider recommendations
-
PostgreSQL sizing - Calculate database requirements
- Estimate: ~1 GB storage per 1M click events
- Recommended: 4 GB+ RAM for PostgreSQL
- Plan for growth: 20-30% buffer capacity
-
Redis capacity (optional but recommended) - Plan cache memory
- Minimum: 512 MB RAM
- Recommended: 2 GB+ for high-traffic deployments
- Enable persistence (RDB or AOF) if you want cache to survive restarts
-
Network bandwidth - Estimate requirements
- Typical: 100-500 requests/second = 10-50 Mbps
- Factor in: redirect traffic, API calls, webhook deliveries, SDK traffic
Domain and DNS
-
Custom domain - Configure your domain for short links
- Example:
go.yourdomain.comorlinks.yourdomain.com - Set up A record pointing to your server
- Example:
-
SSL certificate - Obtain and configure HTTPS
- Use Let's Encrypt (free) or a commercial certificate
- Configure automatic renewal
- Enforce HTTPS redirects via Nginx or Cloudflare
-
DNS propagation - Allow time for DNS changes
- Test from multiple locations
- Verify SSL certificate validity
Security Hardening
Environment Variables
-
Change default credentials - Replace all default values
POSTGRES_PASSWORD- Use a strong, unique password (notchangeme)JWT_SECRET(if enabled) - Generate withopenssl rand -hex 32- Never commit
.envfiles to version control
-
Database credentials - Secure PostgreSQL access
- Create a dedicated application user with limited privileges
- Use connection encryption (SSL/TLS) in production
- Restrict connections to application servers only
-
Redis security (if using Redis) - Protect your cache
- Set
requirepassfor authentication - Bind to localhost or private network only
- Disable dangerous commands (
FLUSHALL,KEYS, etc.)
- Set
Network Security
-
Firewall rules - Restrict network access
- Allow only ports 80, 443, and SSH
- Block public access to PostgreSQL (5432) and Redis (6379)
- Restrict database access to application servers only
-
CORS configuration - Set allowed origins
- Set
CORS_ORIGINto your specific domain(s) instead of* - Restrict API access to known origins in production
- Set
-
Rate limiting (optional) - Protect against abuse
- Set
RATE_LIMIT_ENABLED=true - Configure
RATE_LIMIT_MAX(recommended: 100 requests per window) - Configure
RATE_LIMIT_WINDOW(recommended: 60000ms / 1 minute) - Rate limiting uses Redis for distributed tracking when available
- Set
Database Setup
PostgreSQL Configuration
-
Schema initialization - Verify database is ready
- Core auto-initializes the schema on first startup
- Or run manually:
npm run migrate(from the Core directory)
-
Connection pooling - Review pool settings
- Default: min 2, max 10 connections
- Adjust based on your traffic and server resources
- Monitor pool usage and connection wait times
-
Performance tuning - Optimize PostgreSQL for production
shared_buffers- Set to ~25% of available RAMwork_mem- Set appropriately for your query complexitymax_connections- Match to expected connection count- Enable slow query logging (
log_min_duration_statement = 1000)
-
Backup configuration - Set up automated backups
- Daily full backups via
pg_dump - Consider WAL archiving for point-in-time recovery
- Store backups off-site (S3, separate server, etc.)
- Test restore procedures regularly
- Daily full backups via
Data Retention
- Retention policies - Define how long to keep data
- Click events: decide on retention period (e.g., 90 days, 1 year, indefinite)
- Set up periodic cleanup of old click events if needed
- Archive old data to cold storage for compliance if required
Application Configuration
Environment Setup
-
Production mode - Set Node.js environment
NODE_ENV=production -
Host binding - Bind to all interfaces for external access
HOST=0.0.0.0
PORT=3000 -
Mobile app links (if using mobile SDKs) - Configure
.well-knownendpoints- Set
IOS_TEAM_IDandIOS_BUNDLE_IDfor Universal Links - Set
ANDROID_PACKAGE_NAMEandANDROID_SHA256_FINGERPRINTSfor App Links - Verify endpoints:
curl https://yourdomain.com/.well-known/apple-app-site-association
- Set
Process Management
-
Process manager - Use systemd, PM2, or Docker restart policies
- Docker:
restart: unless-stopped(already set in Core's docker-compose.yml) - systemd: See the Self-Hosting Guide for service file example
- PM2:
pm2 start dist/index.js --name linkforty
- Docker:
-
Restart policies - Configure automatic recovery
- Restart on failure with backoff delay
- Set max restart attempts to prevent crash loops
-
Health checks - Verify the server is responding
- Core exposes a
/healthendpoint - Configure your load balancer or monitoring to check it regularly
- Core exposes a
Monitoring and Logging
Application Monitoring
-
Error tracking - Set up error monitoring
- Use Sentry, Bugsnag, or similar service
- Monitor error rates and types
- Set up alerts for critical errors
-
Performance monitoring - Track response times
- Monitor API response times and redirect latency
- Track database query performance
- Monitor memory and CPU usage
- Set up alerts for anomalies
-
Uptime monitoring - Monitor availability
- Use UptimeRobot, Pingdom, Better Stack, or similar
- Check the
/healthendpoint every 1-5 minutes - Alert on downtime immediately
Logging
-
Structured logging - Fastify logs in JSON format by default
- Log levels: ERROR, WARN, INFO, DEBUG
- Use
NODE_ENV=productionfor appropriate log levels
-
Log rotation - Prevent disk space issues
- Rotate logs daily or by size (100 MB)
- Keep 7-30 days of logs
- Compress old logs
-
Log aggregation (optional) - Centralize logs for searching
- Use ELK Stack, Datadog, Loki + Grafana, or similar
- Enable log searching and filtering
- Set up log-based alerts for error patterns
Key Metrics to Track
-
Business metrics
- Redirects per minute/hour/day
- Active links count
- API requests per second
- Error rates (4xx and 5xx)
- Average redirect latency
-
Infrastructure metrics
- CPU and memory usage
- Disk I/O and free space
- Network traffic
- PostgreSQL connection count and query times
- Redis memory usage and hit rate (if using Redis)
Pre-Launch Testing
-
Staging environment - Test in a production-like environment first
- Mirror production configuration
- Run through the smoke test checklist below
- Test backup and restore procedures
-
Load testing - Verify performance under expected traffic
- Simulate expected traffic (aim for 2x peak)
- Monitor resource usage during the test
- Identify bottlenecks before they hit production
-
Security scan - Run security checks
npm auditfor dependency vulnerabilities- SSL/TLS configuration test (ssllabs.com)
- Verify firewall rules block unauthorized access
Deployment Smoke Tests
After deploying, verify these core functions work:
-
Health check - Server responds
curl https://yourdomain.com/health -
Create a link - API is functional
curl -X POST https://yourdomain.com/api/links \
-H "Content-Type: application/json" \
-d '{"userId":"test","originalUrl":"https://example.com","title":"Test Link"}' -
Redirect works - Short link resolves correctly
curl -I https://yourdomain.com/{shortCode}
# Should return 302 redirect -
Analytics recorded - Click event was tracked
curl "https://yourdomain.com/api/analytics/links/{linkId}?userId=test" -
SSL valid - HTTPS is working correctly
- No mixed content warnings
- Certificate is valid and not expiring soon
-
Mobile app links (if configured) -
.well-knownendpoints respondcurl https://yourdomain.com/.well-known/apple-app-site-association
curl https://yourdomain.com/.well-known/assetlinks.json
Backup and Disaster Recovery
Backup Strategy
-
Database backups - Automated and tested
- Daily full backups (minimum)
- Off-site backup storage
- 30-day retention minimum
- See the Self-Hosting Guide for a backup script example
-
Configuration backups - Save all configuration
.envfile (store securely, not in version control)- Nginx configuration
- SSL certificates (or ensure auto-renewal works)
- Docker Compose file and any customizations
-
Test restores - Verify backups actually work
- Perform a test restore at least monthly
- Document the restore procedure
- Measure restore time
Disaster Recovery
- Recovery plan - Document what to do when things break
- Step-by-step recovery procedures for common failures
- Define acceptable data loss (RPO) and downtime (RTO)
- Assign responsibilities
Compliance and Privacy
-
Data privacy - Review your obligations
- Update your privacy policy to reflect attribution data collection
- Implement data export and deletion procedures if required (GDPR, CCPA)
- Define and document data retention periods
-
IP geolocation data - Understand what's collected
- Core tracks IP addresses, geolocation, and user agents for click analytics
- Ensure this aligns with your privacy policy
- Consider IP anonymization if required by your jurisdiction
Post-Launch
-
Monitor closely for the first 48 hours
- Watch error rates, response times, and resource usage
- Be ready to roll back if issues arise
-
Document learnings - Update your runbooks
- Note any issues encountered during deployment
- Update procedures based on real experience
-
Schedule regular maintenance
- Monthly: review metrics, update dependencies, verify backups
- Quarterly: security audit, performance review, capacity planning
Getting Help
- Self-Hosting Guide - Complete deployment instructions
- GitHub Discussions - Community support
- Report Issues - Bug reports