AWS Performance Notes

Notes

Unblock wait loop in Lambda

And finally, many Node.js client libraries, such as the Redis client, prevent the invocation from finishing, in which case, you need to set the callbackWaitsForEmptyEventLoop property in the invocation context object to false, just like this :

context.callbackWaitsForEmptyEventLoop = false   // true by default.


// Times out due to typo
exports.function1 = (event, context, callback) => {
    setInterval(() => console.log('Long wait'), 100000);
    context.callbackWaitsForEmtpyEventLoop = false;
    callback(null, 'Hello from Lambda');
};

Aurora has latency issues

PS – The serverless Aurora has some harsh limitations: MySql only, and a variant that doesn’t have support for a very current ANSI sql — no subqueries, no WITH, etc. Plus, the cold start time is horrible for web UI’s that are intermittently used. Tried to use it, but had to revert back to standard RDS instances.

Tips from Jeremy Daly

  1. Implement a good caching strategy
  • As your application scales, use REDIS to cache common data queries.
  • REDIS’s maxclient default is 65,000, far greater than limit for RDS.
  1. Lower your connection timeouts RDS doesn’t give your root account the SUPER privilege, but you can create "RDS DB Parameter Groups" that allow you to set the wait_timeout and interactive_timeout to lower values. (the default is 8 hours, make it 10 mins).
  2. Limit concurrent executions.
  3. Limit connections per username. MAX USER_CONNECTIONS can be configured.
  4. Clear connections with a proxy function Even without SUPER privilege, RDS does allow SHOW PROCESSLIST. You could trigger a proxy Lambda function and have it inspect all the open connections. Then it can issue a CALL mysql.rds_kill(thread-ID) on sleeping connections with high time values.
  5. Increase max_connections setting. As I mentioned earlier, RDS lets you create “RDS DB Parameter Groups” to adjust your database’s default settings. This can be used to set the max_connections value up to 16,000 connections!
  6. Use the serverless-mysql NPM module:

// Require and initialize with default options const mysql = require('serverless-mysql')() // <-- initialize with function call

mysql.config({
host : process.env.ENDPOINT, database : process.env.DATABASE, user : process.env.USERNAME, password : process.env.PASSWORD

})

await mysql.connect() // redundant since it is done automatically for you.

// Simple query let results = await query('SELECT * FROM table')

// Query with placeholder values let results = await query('SELECT * FROM table WHERE name = ?', ['serverless'])

// Perform connection management tasks await mysql.end() // Will terminate connection only if needed. // If connection usage is high, will terminate. mysql.quit() // Gracefully terminate the connection

// Get the underlying mysql connection object let connection = mysql.getClient()