Skip to content

Troubleshooting

This guide covers common issues you might encounter when using Easy Deploy and provides solutions to resolve them quickly.

  • Missing dependencies: Package.json missing required packages
  • Node version mismatch: Application requires specific Node.js version
  • Build script errors: Errors in build commands or scripts
  • Environment variables: Missing required environment variables

Check build logs

Terminal window
# View detailed build logs
easydeploy logs APP_NAME --build
# View real-time deployment logs
easydeploy deploy APP_NAME --follow

Fix dependency issues

Terminal window
# Ensure all dependencies are listed
npm install --save missing-package
# Update package-lock.json
npm install
# Check for security vulnerabilities
npm audit fix

Specify Node.js version

package.json
{
"engines": {
"node": "18.x",
"npm": "9.x"
}
}

Symptoms: Deployment takes longer than 10 minutes and times out

Solutions:

  1. Optimize build process:

    • Remove unnecessary files from build
    • Use .easydeploy-ignore to exclude large directories
    • Enable build caching in .easydeploy.yml
  2. Break down large builds:

    .easydeploy.yml
    build:
    timeout: 20m # Increase timeout
    cache: true # Enable caching
    parallel: true # Enable parallel builds

Symptoms: Application builds successfully but fails health checks

Causes:

  • Application not starting properly
  • Wrong port configuration
  • Health check endpoint not responding

Solutions:

  1. Check port configuration:

    Terminal window
    const PORT = process.env.PORT || 3000;
    app.listen(PORT, '0.0.0.0', () => {
    console.log(`Server running on port ${PORT}`);
    });
  2. Implement health check endpoint:

    Terminal window
    app.get('/health', (req, res) => {
    res.status(200).json({ status: 'healthy' });
    });
  3. Configure health checks:

    .easydeploy.yml
    health_check:
    path: "/health"
    timeout: 30s
    interval: 10s

Symptoms:

  • Application crashes with “out of memory” errors
  • Slow response times
  • Frequent restarts

Solutions:

  1. Increase memory allocation:

    .easydeploy.yml
    resources:
    memory: 1GB # Increase from default 512MB
  2. Optimize memory usage:

    Terminal window
    // Implement garbage collection monitoring
    if (process.env.NODE_ENV === 'production') {
    setInterval(() => {
    if (global.gc) {
    global.gc();
    }
    }, 30000);
    }
  3. Memory leak detection:

    Terminal window
    # Monitor memory usage
    easydeploy metrics APP_NAME --metric=memory --period=24h

Detection:

  • Gradually increasing memory usage
  • Application slowdown over time
  • Eventual crashes

Solutions:

  1. Profile memory usage:

    Terminal window
    // Add memory monitoring
    setInterval(() => {
    const used = process.memoryUsage();
    console.log('Memory usage:', {
    rss: Math.round(used.rss / 1024 / 1024) + 'MB',
    heapTotal: Math.round(used.heapTotal / 1024 / 1024) + 'MB',
    heapUsed: Math.round(used.heapUsed / 1024 / 1024) + 'MB'
    });
    }, 60000);
  2. Common leak sources:

    • Event listeners not removed
    • Timers not cleared
    • Unclosed database connections
    • Large objects in global scope

Symptoms:

  • High response times (>1000ms)
  • Timeouts on client side
  • Poor user experience

Diagnosis:

Terminal window
# Check response time metrics
easydeploy metrics APP_NAME --metric=response_time --period=1h
# Monitor application logs
easydeploy logs APP_NAME --follow --level=info

Solutions:

  1. Database optimization:

    Terminal window
    // Add database connection pooling
    const pool = new Pool({
    connectionString: process.env.DATABASE_URL,
    max: 20,
    idleTimeoutMillis: 30000,
    connectionTimeoutMillis: 2000,
    });
  2. Implement caching:

    Terminal window
    const redis = require('redis');
    const client = redis.createClient(process.env.REDIS_URL);
    // Cache frequently accessed data
    app.get('/api/data', async (req, res) => {
    const cacheKey = `data:${req.params.id}`;
    let data = await client.get(cacheKey);
    if (!data) {
    data = await database.getData(req.params.id);
    await client.setex(cacheKey, 300, JSON.stringify(data));
    } else {
    data = JSON.parse(data);
    }
    res.json(data);
    });
  3. Optimize API calls:

    Terminal window
    // Implement request batching
    const batchRequests = (requests) => {
    return Promise.all(requests.map(req =>
    fetch(req.url, req.options)
    ));
    };

Symptoms:

  • “Connection timeout” errors
  • Intermittent database connectivity
  • Application hanging on database calls

Solutions:

  1. Check connection configuration:

    Terminal window
    const dbConfig = {
    connectionString: process.env.DATABASE_URL,
    connectionTimeoutMillis: 5000,
    idleTimeoutMillis: 30000,
    max: 10 // connection pool size
    };
  2. Implement retry logic:

    Terminal window
    async function queryWithRetry(query, params, maxRetries = 3) {
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
    return await db.query(query, params);
    } catch (error) {
    if (attempt === maxRetries) throw error;
    await new Promise(resolve => setTimeout(resolve, 1000 * attempt));
    }
    }
    }

Symptoms:

  • “Pool exhausted” errors
  • New connections rejected
  • Application stops responding

Solutions:

  1. Increase pool size:

    Terminal window
    const pool = new Pool({
    max: 20, // Increase from default
    min: 2,
    acquire: 30000,
    idle: 10000
    });
  2. Ensure connections are released:

    Terminal window
    // Always use try/finally
    async function getData() {
    const client = await pool.connect();
    try {
    return await client.query('SELECT * FROM users');
    } finally {
    client.release();
    }
    }

Detection:

Terminal window
# Enable slow query logging
easydeploy database DB_NAME --enable-slow-query-log
# View slow queries
easydeploy database DB_NAME --slow-queries --limit=10

Solutions:

  1. Add indexes:

    Terminal window
    -- Identify missing indexes
    EXPLAIN ANALYZE SELECT * FROM users WHERE email = '[email protected]';
    -- Add appropriate index
    CREATE INDEX idx_users_email ON users(email);
  2. Optimize queries:

    Terminal window
    -- Before: N+1 query problem
    SELECT * FROM users;
    -- Then for each user:
    SELECT * FROM orders WHERE user_id = ?;
    -- After: Single join query
    SELECT u.*, o.* FROM users u
    LEFT JOIN orders o ON u.id = o.user_id;

Symptoms:

  • “SSL certificate not valid” errors
  • Browser security warnings
  • HTTPS not working

Solutions:

  1. Check certificate status:

    Terminal window
    curl -I https://yourdomain.com
    easydeploy ssl APP_NAME --status
  2. Force certificate renewal:

    Terminal window
    easydeploy ssl APP_NAME --renew
  3. Verify domain configuration:

    Terminal window
    # Check DNS records
    dig yourdomain.com
    nslookup yourdomain.com

Symptoms:

  • Browser console warnings about mixed content
  • Some resources not loading over HTTPS

Solutions:

  1. Update resource URLs:

    Terminal window
    <!-- Before -->
    <script src="http://example.com/script.js"></script>
    <!-- After -->
    <script src="https://example.com/script.js"></script>
  2. Use protocol-relative URLs:

    Terminal window
    <script src="//example.com/script.js"></script>
  3. Configure Content Security Policy:

    Terminal window
    app.use((req, res, next) => {
    res.setHeader('Content-Security-Policy',
    "default-src 'self' https:; img-src 'self' https: data:");
    next();
    });

Symptoms:

  • Application crashes on startup
  • “undefined” environment variable errors
  • Features not working correctly

Solutions:

  1. Check variable configuration:

    Terminal window
    easydeploy env APP_NAME --list
  2. Set missing variables:

    Terminal window
    easydeploy env APP_NAME --set KEY=value
  3. Use default values in code:

    Terminal window
    const dbUrl = process.env.DATABASE_URL || 'postgresql://localhost:5432/myapp';
    const port = process.env.PORT || 3000;
    const nodeEnv = process.env.NODE_ENV || 'development';

Detection:

Terminal window
// Add environment validation
function validateEnvironment() {
const required = ['DATABASE_URL', 'JWT_SECRET', 'API_KEY'];
const missing = required.filter(key => !process.env[key]);
if (missing.length > 0) {
console.error('Missing required environment variables:', missing);
process.exit(1);
}
}
validateEnvironment();

Symptoms:

  • 429 “Too Many Requests” responses
  • API calls being rejected
  • Slow application performance

Solutions:

  1. Implement client-side rate limiting:

    Terminal window
    class RateLimiter {
    constructor(maxRequests, timeWindow) {
    this.maxRequests = maxRequests;
    this.timeWindow = timeWindow;
    this.requests = [];
    }
    async makeRequest(requestFn) {
    const now = Date.now();
    this.requests = this.requests.filter(time => now - time < this.timeWindow);
    if (this.requests.length >= this.maxRequests) {
    const waitTime = this.timeWindow - (now - this.requests[0]);
    await new Promise(resolve => setTimeout(resolve, waitTime));
    }
    this.requests.push(now);
    return requestFn();
    }
    }
  2. Add retry logic with exponential backoff:

    Terminal window
    async function apiCallWithRetry(url, options, maxRetries = 3) {
    for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
    const response = await fetch(url, options);
    if (response.status === 429) {
    const retryAfter = response.headers.get('Retry-After') || attempt * 2;
    await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
    continue;
    }
    return response;
    } catch (error) {
    if (attempt === maxRetries) throw error;
    await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
    }
    }
    }

Symptoms:

  • “CORS policy” errors in browser console
  • API calls failing from frontend
  • Cross-origin request blocked

Solutions:

  1. Configure CORS properly:

    Terminal window
    const cors = require('cors');
    app.use(cors({
    origin: process.env.FRONTEND_URL || 'http://localhost:3000',
    credentials: true,
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    allowedHeaders: ['Content-Type', 'Authorization']
    }));
  2. Handle preflight requests:

    Terminal window
    app.options('*', cors()); // Enable preflight for all routes
Terminal window
# Search for errors
easydeploy logs APP_NAME --level=error --since=1h
# Search for specific patterns
easydeploy logs APP_NAME --grep="database connection"
# Follow logs in real-time
easydeploy logs APP_NAME --follow
Terminal window
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
),
transports: [
new winston.transports.Console()
]
});
// Use structured logging
logger.info('User logged in', {
userId: user.id,
email: user.email,
ip: req.ip,
userAgent: req.get('User-Agent')
});
logger.error('Database error', {
error: error.message,
stack: error.stack,
query: query,
duration: queryTime
});
Terminal window
// Add custom metrics
const client = require('prom-client');
const httpDuration = new client.Histogram({
name: 'http_request_duration_seconds',
help: 'Duration of HTTP requests in seconds',
labelNames: ['method', 'route', 'status']
});
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = (Date.now() - start) / 1000;
httpDuration
.labels(req.method, req.route?.path || req.url, res.statusCode)
.observe(duration);
});
next();
});
  1. Documentation: Check this guide and API documentation
  2. Community Forum: Search existing solutions
  3. Support Tickets: For account-specific issues
  4. Status Page: Check for service outages
  • Account issues: Billing, permissions, access problems
  • Platform bugs: Unexpected behavior in Easy Deploy platform
  • Security concerns: Potential security vulnerabilities
  • Performance issues: Platform-level performance problems

When contacting support, provide:

  • Application name and ID
  • Deployment ID (if applicable)
  • Error messages and stack traces
  • Steps to reproduce the issue
  • Expected vs actual behavior
  • Browser and operating system (for frontend issues)
Terminal window
# Check application status
easydeploy status APP_NAME
# View recent deployments
easydeploy deployments APP_NAME --limit=10
# Check resource usage
easydeploy metrics APP_NAME --metric=cpu,memory --period=24h
# Restart application
easydeploy restart APP_NAME
# View configuration
easydeploy config APP_NAME

For critical issues:

  1. Check status page for known outages
  2. Enable maintenance mode if needed:
    Terminal window
    easydeploy maintenance APP_NAME --enable
  3. Rollback to previous version:
    Terminal window
    easydeploy rollback APP_NAME --to=DEPLOYMENT_ID
  4. Contact emergency support for critical production issues

Remember: Most issues can be resolved by checking logs, verifying configuration, and following the troubleshooting steps in this guide.