diff --git a/requirements.txt b/requirements.txt
index 5c7639c236dbd4a1a83c19240ff743cdc88d41ca..35dd243ecdd341c9300901ac2e6a6beb2ff55643 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,3 @@
 dnspython
 requests
+twilio
diff --git a/sms-notify.tf b/sms-notify.tf
new file mode 100644
index 0000000000000000000000000000000000000000..62a167b31525a27ed94ae45f6a90c0ce9e4b481e
--- /dev/null
+++ b/sms-notify.tf
@@ -0,0 +1,172 @@
+variable "twilio_account_sid" {
+  description = "Twilio account SID."
+}
+
+variable "twilio_api_key" {
+  description = "Twilio API key."
+}
+
+variable "twilio_api_secret" {
+  description = "Twilio API secret."
+}
+
+# It would have been nicer to buy the phone number with Terraform and the
+# Twilio provider. unfortunately the sign up for the provider is closed right
+# now. So instead the friendly name, that's something.
+variable "twilio_from_number" {
+  default     = "AmILive"
+  description = "Twilio from phone number."
+}
+
+resource "aws_lambda_function" "sms_notify" {
+  runtime           = var.runtime
+  function_name     = "${local.function_name_prefix}-sms-notify"
+  role              = local.lambda_role_arn
+  source_code_hash  = filebase64sha256("payload.zip")
+  s3_bucket         = local.payloads_bucket_name
+  s3_key            = local.payload_object_name
+  s3_object_version = local.payload_object_version
+  package_type      = "Zip"
+  handler           = "sms_notify.handler"
+  description       = "Send SMS message notification using Twilio."
+  memory_size       = var.memory_size
+  tags              = local.common_tags
+  timeout           = var.timeout
+
+  environment {
+    variables = {
+      ENV                = local.env
+      MODULE             = local.module
+      TOPIC_ARN          = local.topic_arn
+      VERSION            = local.payload_object_version
+      TWILIO_ACCOUNT_SID = var.twilio_account_sid
+      TWILIO_API_KEY     = var.twilio_api_key
+      TWILIO_API_SECRET  = var.twilio_api_secret
+      TWILIO_FROM_NUMBER = var.twilio_from_number
+      TWILIO_TO_NUMBER   = local.my_phone_number
+    }
+  }
+
+  # Create the log group with retention before the function is created.
+  # Otherwise it's created without retention and need to be imported.
+  depends_on = [
+    aws_cloudwatch_log_group.sms_notify,
+  ]
+}
+
+locals {
+  sms_notify_function_arn     = aws_lambda_function.sms_notify.arn
+  sms_notify_function_name    = aws_lambda_function.sms_notify.function_name
+  sms_notify_function_version = aws_lambda_function.sms_notify.version
+}
+
+output "sms_notify_function_arn" {
+  description = "ARN of the SMS notification Lambda function."
+  value       = local.sms_notify_function_arn
+}
+
+output "sms_notify_function_name" {
+  description = "Name of the SMS notification Lambda function."
+  value       = local.sms_notify_function_name
+}
+
+output "sms_notify_function_version" {
+  description = "Version of the SMS notification Lambda function."
+  value       = local.sms_notify_function_version
+}
+
+resource "aws_lambda_alias" "sms_notify" {
+  name             = "${local.function_name_prefix}_${local.sms_notify_function_name}"
+  function_name    = local.sms_notify_function_arn
+  function_version = local.sms_notify_function_version
+}
+
+locals {
+  sms_notify_function_alias_arn  = aws_lambda_alias.sms_notify.arn
+  sms_notify_function_alias_name = aws_lambda_alias.sms_notify.name
+}
+
+output "sms_notify_function_alias_arn" {
+  description = "ARN of the SMS notification Lambda function alias."
+  value       = local.sms_notify_function_alias_arn
+}
+
+output "sms_notify_function_alias_name" {
+  description = "Name of the SMS notification Lambda function alias."
+  value       = local.sms_notify_function_alias_name
+}
+
+resource "aws_lambda_permission" "sms_notify" {
+  statement_id  = "AllowExecutionFromSNS"
+  action        = "lambda:InvokeFunction"
+  principal     = "sns.amazonaws.com"
+  source_arn    = local.topic_arn
+  function_name = local.sms_notify_function_name
+}
+
+resource "aws_sns_topic_subscription" "sms_notify" {
+  endpoint  = local.sms_notify_function_arn
+  protocol  = "lambda"
+  topic_arn = local.topic_arn
+  depends_on = [
+    aws_lambda_permission.sms_notify,
+  ]
+}
+resource "aws_cloudwatch_log_group" "sms_notify" {
+  name              = "/aws/lambda/${local.function_name_prefix}-sms-notify"
+  retention_in_days = var.log_retention
+  tags              = local.common_tags
+}
+
+locals {
+  sms_notify_log_group_arn  = aws_cloudwatch_log_group.sms_notify.arn
+  sms_notify_log_group_name = aws_cloudwatch_log_group.sms_notify.name
+}
+
+output "sms_notify_log_group_arn" {
+  description = "ARN of the CloudWatch log groups for the SMS notify Lambda function invocations."
+  value       = local.sms_notify_log_group_arn
+}
+
+output "sms_notify_log_group_name" {
+  description = "Name of the CloudWatch log groups for the SMS notify Lambda function invocations."
+  value       = local.sms_notify_log_group_name
+}
+
+data "aws_iam_policy_document" "sms_notify" {
+  statement {
+    effect = "Allow"
+
+    actions = [
+      "logs:CreateLogStream",
+      "logs:PutLogEvents",
+    ]
+
+    resources = [local.sms_notify_log_group_arn, ]
+  }
+}
+
+locals {
+  sms_notify_log_policy_doc = data.aws_iam_policy_document.sms_notify.json
+}
+
+resource "aws_iam_policy" "sms_notify_log" {
+  name   = "${local.module}-${local.env}-sms-notify-log"
+  policy = local.sms_notify_log_policy_doc
+  tags   = local.common_tags
+}
+
+locals {
+  sms_notify_log_policy_arn  = aws_iam_policy.log.arn
+  sms_notify_log_policy_name = aws_iam_policy.log.name
+}
+
+output "sms_notify_log_policy_arn" {
+  value       = local.sms_notify_log_policy_arn
+  description = "CloudWatch log IAM policy for SMS notifications ARN."
+}
+
+output "sms_notify_log_policy_name" {
+  value       = local.sms_notify_log_policy_name
+  description = "CloudWatch log IAM policy for SMS notifications name."
+}
diff --git a/sns.tf b/sns.tf
index 725e2e56dbfd217070759383b159c1cfe987eddb..6ddf0d9e1380330a45144f574e9521c301eb095d 100644
--- a/sns.tf
+++ b/sns.tf
@@ -25,6 +25,10 @@ variable "subscriptions" {
   description = "A list of subscriptions to the SNS topic."
 }
 
+locals {
+  my_phone_number = var.subscriptions[0][0]
+}
+
 output "subscriptions" {
   description = "A list of subscriptions to the SNS topic."
   value       = var.subscriptions
diff --git a/src/sms_notify.py b/src/sms_notify.py
new file mode 100644
index 0000000000000000000000000000000000000000..4564f2d659681b9da89a517e4e6a2c7b782d1622
--- /dev/null
+++ b/src/sms_notify.py
@@ -0,0 +1,26 @@
+import os
+import twilio.rest  # pylint: disable=import-error
+
+
+TWILIO_ACCOUNT_SID = os.environ["TWILIO_ACCOUNT_SID"]
+TWILIO_API_KEY = os.environ["TWILIO_API_KEY"]
+TWILIO_API_SECRET = os.environ["TWILIO_API_SECRET"]
+TWILIO_FROM_NUMBER = os.environ["TWILIO_FROM_NUMBER"]
+TWILIO_TO_NUMBER = os.environ["TWILIO_TO_NUMBER"]
+
+
+# pylint: disable=unused-argument
+def handler(event, context):
+    message = event["Records"][0]["Sns"]["Message"]
+    client = twilio.rest.Client(
+        TWILIO_API_KEY, TWILIO_API_SECRET, TWILIO_ACCOUNT_SID
+    )
+    client.messages.create(
+        body=message,
+        from_=TWILIO_FROM_NUMBER,
+        to=TWILIO_TO_NUMBER,
+    )
+
+
+if __name__ == "__main__":
+    handler({"Records": [{"Sns": {"Message": "foo"}}]}, "context")