Serverless In Just a Few Lines of Code
Pulumi makes serverless applications easy by letting you focus on business logic and managing infrastructure in the same familiar language you’re already writing your code in.
Any code, any cloud, any language.
What is Serverless?
Serverless, or function-based, computing enables you to build and run applications and services without thinking about the server infrastructure on which the functions depend. 'Serverless' applications of course require servers (typically cloud infrastructure, or Kubernetes clusters), but don't require you to provision, scale, and manage any servers.
The reduced operational overhead of serverless computing means teams can focus on the business and application logic they need: the development of products vs the management of the infrastructure for them.
Building Blocks of Serverless Programming
Building serverless applications can be considered to be a composition of a series of standardized building blocks. For instance, serverless services can provide compute, storage, data storage, messaging/queues and orchestration. With just those blocks, extremely powerful applications can be composed and delivered with minimal infrastructure concerns.
| Building Block | AWS | Azure | Google Cloud |
|---|---|---|---|
| API | Lambda | Functions | Cloud Functions |
| Storage | S3 | Blob Storage | Cloud Storage |
| Data Storage | DynamoDB | Cosmos DB | Cloud Datatable |
| Timer | CloudWatch | Monitor | Stackdriver Monitoring |
| Queue | SQS | Queue Storage | Cloud Pub/Sub |
| Topic | SNS | Queue Storage | Cloud Pub/Sub |
Pulumi makes it simple to interact with serverless services available from the major cloud vendors, and with Kubernetes.
Creating a Serverless REST API
This example shows how to create a simple REST API that counts the number of times a route has been hit. To implement this API, we need a DynamoDB table, an API endpoint, and a Lambda function.
import * as aws from "@pulumi/aws";
import * as awsx from "@pulumi/awsx";
// Create a mapping from 'route' to a count.
let counterTable = new aws.dynamodb.Table("counterTable", {
attributes: [{ name: "id", type: "S" }],
hashKey: "id",
readCapacity: 5,
writeCapacity: 5,
});
// Create an API endpoint.
let endpoint = new awsx.apigateway.API("hello-world", {
routes: [{
path: "/{route+}",
method: "GET",
eventHandler: async (event) => {
let route = event.pathParameters!["route"];
let client = new aws.sdk.DynamoDB.DocumentClient();
// Get previous value and increment our table entry.
let tableData = await client.get({
TableName: counterTable.name.get(),
Key: { id: route },
ConsistentRead: true,
}).promise();
let value = tableData.Item;
let count = (value && value.count) || 0;
await client.put({
TableName: counterTable.name.get(),
Item: { id: route, count: ++count },
}).promise();
return {
statusCode: 200,
body: JSON.stringify({ route, count }),
};
},
}],
});
exports.endpoint = endpoint.url;
Using storage buckets easily
Pulumi makes it easy to setup storage in the cloud. Events raised by the storage object can be handled by Lambda functions as actual lambdas in code.
This example sets up a storage bucket (using S3 on AWS) and a simple Lambda function to respond to new items being added to the bucket.
const aws = require("@pulumi/aws");
// A storage bucket.
const videos = new aws.s3.Bucket("bucket");
// Trigger a Lambda function when something is added.
videos.onPut("onNewVideo", bucketArgs => {
console.log(`*** New Item in Bucket`);
}
// Export the bucket name.
exports.bucketName = videos.bucket;
Stash info into a document database
This example uses a serverless timer that fetches the Hacker News homepage every day at 8:30AM and stashes it into a document database, making use of Pulumi’s ability to reference resources by capturing them inside of serverless lambdas.
const aws = require("@pulumi/aws");
const snapshots = new aws.dynamodb.Table("snapshots", {
attributes: [{ name: "id", type: "S", }],
hashKey: "id", billingMode: "PAY_PER_REQUEST",
});
aws.cloudwatch.onSchedule("daily-yc-snapshot", "cron(30 8 * * ? *)", () => {
require("https").get("https://news.ycombinator.com", res => {
let content = "";
res.setEncoding("utf8");
res.on("data", chunk => content += chunk);
res.on("end", () => new aws.sdk.DynamoDB.DocumentClient().put({
TableName: snapshots.name.get(),
Item: { date: Date.now(), content },
}).promise());
}).end();
});
Super-simple serverless cron jobs
Pulumi makes it straightforward to schedule serverless functions on a cron schedule. Using AWS EventBridge (CloudWatch Events), you can trigger a Lambda function on any schedule without needing to manage additional orchestration infrastructure.
Schedules can be specified using either a rate expression or a cron expression. This example creates an EventBridge rule and wires it to a Lambda function that prints the current time to the console every minute.
import * as aws from "@pulumi/aws";
const rule = new aws.cloudwatch.EventRule("everyMinute", {
scheduleExpression: "rate(1 minute)",
});
const fn = new aws.lambda.CallbackFunction("handler", {
callback: async () => {
console.log(`everyMinute: ${Date.now()}`);
},
});
new aws.lambda.Permission("allow-events", {
function: fn,
action: "lambda:InvokeFunction",
principal: "events.amazonaws.com",
sourceArn: rule.arn,
});
new aws.cloudwatch.EventTarget("everyMinuteTarget", {
rule: rule.name,
arn: fn.arn,
});
Post AWS SQS Messages to Slack
This example wires up an AWS Lambda to an SQS queue and posts a message to Slack whenever a new item arrives. Pulumi provisions all the infrastructure, while you write the event handler as an ordinary TypeScript function.
import * as aws from "@pulumi/aws";
const queue = new aws.sqs.Queue("mySlackQueue", { visibilityTimeoutSeconds: 180 });
const fn = new aws.lambda.CallbackFunction("mySlackPoster", {
callback: async (event: aws.sqs.QueueEvent) => {
const { WebClient } = require("@slack/web-api");
const client = new WebClient(process.env.SLACK_TOKEN);
for (const rec of event.Records) {
await client.chat.postMessage({
channel: process.env.SLACK_CHANNEL!,
text: `*Msg ${rec.messageId}*:\n${rec.body}\n(with :love_letter: from Pulumi)`,
});
console.log(`Posted SQS message ${rec.messageId}`);
}
},
});
new aws.lambda.EventSourceMapping("queueTrigger", {
eventSourceArn: queue.arn,
functionName: fn.arn,
batchSize: 1,
});
export const queueURL = queue.id;
Subscribe to an SNS endpoint
This example uses an SNS topic to hold a list of website URLs to crawl, and does so everytime a new message arrives.
import * as aws from "@pulumi/aws";
import * as fetch from "node-fetch";
const topic = new aws.sns.Topic("sites-to-process-topic");
topic.onEvent("for-each-url", async (event) => {
const records = event.Records || [];
for (const record of records) {
// Fetch the contents at the URL
const url = record.Sns.Message;
console.log(`${url}: Getting`);
try {
const res = await fetch.default(url);
} catch (err) {
console.log(`${url}: Failed to GET`);
return;
}
}
});
How Pulumi Works
Build
- Code in modern languages
- Share and reuse patterns
- Use your favorite IDE and tools

Deploy
- Preview changes
- Run
pulumi upto deploy - Integrate with CI/CD

Manage
- Audit all changes
- Manage complex environments
- Implement policies and controls
Get Started with Pulumi
Use Pulumi's open source SDK to create, deploy, and manage infrastructure on any cloud.