One of the biggest fears with serverless applications concerns vendor lock-in. This is a common fear with any move to cloud technology. For example, if you start committing to using Lambda, then you are committing to using AWS and either you will not be able to move to another cloud provider or you will not be able to afford transition to a cloud provider.
While this is understandable, there are many ways to develop applications to make a vendor switch using functions easier. A popular and preferred strategy is to pull the cloud provider logic out of the handler files so it can easily be switched to another provider. The following code illustrates a poor example of abstracting cloud provider logic.
The following code shows the handler file for a function that includes all of the database logic bound to the FaaS provider (AWS, in this case):
const database = require('database').connect();
const mail = require('mail');
module.exports.saveCustomer = (event, context, callback) => {
const customer = {
emailAddress: event.email,
createdAt: Date.now(),
};
database.saveCustomer(customer, (err) => {
if (err) {
callback(err);
} else {
mail.sendEmail(event.email);
callback();
}
});
};
The following code illustrates a better example of abstracting the cloud provider logic.
The following code shows a handler file that is abstracted away from the FaaS provider logic by creating a separate Users class:
class Customers {
constructor(database, mail) {
this.database = database;
this.mail = mail;
}
save(emailAddress, callback) {
const customer = {
emailAddress: emailAddress,
createdAt: Date.now(),
};
this.database.saveCustomer(customer, (err) => {
if (err) {
callback(err);
} else {
this.mail.sendEmail(emailAddress);
callback();
}
});
}
}
module.exports = Customers;
const database = require('database').connect();
const mail = require('mail');
const Customers = require('customers');
let customers = new Customers(database, mail);
module.exports.saveCustomer = (event, context, callback) => {
customers.save(event.email, callback);
};
The second method is preferable both for avoiding vendor lock-in and for testing. Removing the cloud provider logic from the event handler makes the application more flexible and applicable to many providers. It makes testing easier by allowing you to write unit tests to ensure it is working properly in a traditional way. You can also write integration tests to verify that integrations with external services are working properly.
Most of the serverless offerings by cloud providers are implemented in a similar way. However, if you had to switch vendors, you would definitely need to update your operational toolsets that you use for monitoring, deployments, and so on. You might have to change your code's interface to be compatible with the new cloud provider.
If you are using other solutions provided by the cloud vendor that are very much specific to the cloud provider, then moving between vendors becomes extremely difficult, as you would have to re-architect your application with the solutions that the new cloud provider provides.