Building a Real-Time Maintenance Task Notification System with Lambda, Google Apps Script, and CloudFront
The maintenance.queenofsandiego.com tool needed a critical capability: surfacing newly added tasks to the operations team with appropriate urgency levels. This post details the architecture, implementation decisions, and deployment strategy for a production-grade notification system that integrates Google Apps Script, AWS Lambda, CloudFront, and email delivery.
The Problem
The maintenance tracking tool had no mechanism to notify team members (Sergio and operations) when new tasks were added. Travis could add tasks via the web interface, but there was no visibility into what was new. Additionally, the team needed:
- Differentiated notification urgency based on task criticality
- Configurable notification cadence (immediate vs. daily digest)
- Staging/production separation for testing
- Integration with Google Calendar for crew awareness
- Support for multiple notification channels (email, calendar events)
Architecture Overview
The solution implements a three-layer notification pipeline:
- Frontend Layer: Modified maintenance.queenofsandiego.com staging HTML to capture task metadata
- Middleware Layer: Google Apps Script handlers routing `log_maintenance` POST requests to persistence and notification services
- Backend Layer: AWS Lambda function processing tasks, evaluating criticality, and triggering notifications
This architecture leverages existing infrastructure while maintaining clear separation of concerns and testability.
Technical Implementation
Frontend Changes: Task Metadata Capture
Modified /Users/cb/Documents/repos/sites/queenofsandiego.com/tools/maintenance/staging-index.html to capture extended task information when logging new maintenance items:
// Task submission now includes criticality levels
const taskPayload = {
action: 'log_maintenance',
task_description: inputValue,
criticality: 'standard' | 'high' | 'emergency',
assigned_to: crewMember,
eta_hours: estimatedDuration,
timestamp: new Date().toISOString()
};
The staging HTML is deployed to the S3 bucket serving the CloudFront distribution, allowing testing before production rollout. This is critical for a tool managing operational safety items.
Google Apps Script Handler
Created MaintenancePersistence.gs to handle persistence logic separately from booking automation:
function logMaintenanceTask(data) {
// Validate criticality level
const validCriticalities = ['standard', 'high', 'emergency'];
const criticality = validCriticalities.includes(data.criticality)
? data.criticality
: 'standard';
// Create persistence record
const record = {
id: Utilities.getUuid(),
task: data.task_description,
criticality: criticality,
created_at: new Date().toISOString(),
assigned_to: data.assigned_to,
status: 'pending'
};
// Call Lambda for notification evaluation
const lambdaPayload = {
action: 'evaluate_maintenance_task',
task: record,
team_email: 'jadasailing@gmail.com'
};
invokeLambdaNotification(lambdaPayload);
return record;
}
Modified BookingAutomation.gs to route maintenance actions:
// In doPost handler, added routing:
if (data.action === 'log_maintenance') {
const result = logMaintenanceTask(data);
return ContentService.createTextOutput(JSON.stringify(result));
}
Created MaintenanceCalendar.gs to handle Google Calendar integration for crew visibility:
function createMaintenanceCalendarEvent(taskRecord) {
const calendar = CalendarApp.getCalendarById('jada2026@jadasailing.com');
const event = calendar.createEvent(
`[${taskRecord.criticality.toUpperCase()}] ${taskRecord.task}`,
new Date(taskRecord.created_at),
new Date(new Date(taskRecord.created_at).getTime() + (taskRecord.eta_hours * 60 * 60 * 1000))
);
// Color-code by criticality
const colorMap = {
'emergency': CalendarApp.EventColor.RED,
'high': CalendarApp.EventColor.ORANGE,
'standard': CalendarApp.EventColor.BLUE
};
event.setColor(colorMap[taskRecord.criticality]);
return event.getId();
}
Lambda Notification Service
Implemented a Lambda function (deployed using existing patterns from tips-box) with IAM role configured for CloudWatch Logs and SES email delivery. The function evaluates task criticality against industry best practices for incident response:
// Notification timing rules based on industry SLAs
const notificationRules = {
'emergency': {
immediate: true,
channels: ['email', 'sms', 'calendar'],
recipients: ['sergio@jada', 'cb@jada'],
escalate_after_minutes: 15
},
'high': {
immediate: true,
channels: ['email', 'calendar'],
recipients: ['sergio@jada'],
digest_cutoff: 0 // Include in immediate email
},
'standard': {
immediate: false,
channels: ['email', 'calendar'],
recipients: ['sergio@jada'],
digest_cutoff: 24 // Include in daily digest
}
};
// Lambda evaluates task against rules and triggers notifications
Infrastructure Decisions
Staging vs. Production
Currently, maintenance.queenofsandiego.com uses a single CloudFront distribution and S3 bucket. For staging testing, we deploy the modified HTML to a /staging path within the same bucket, with CloudFront cache invalidation after each deployment:
aws s3 cp staging-index.html s3://maintenance-bucket/staging/index.html
aws cloudfront create-invalidation --distribution-id XXXXXXXXXXXX --paths "/staging/*"
Test notifications are routed to jadasailing@gmail.com until the feature is promoted to production. This allows the team to validate notification timing and content without spamming production channels.
Email Delivery
Using SES (Simple Email Service) with a verified sending identity. Emails are templated with task metadata, direct action links, and criticality indicators. The template respects email client rendering constraints while maintaining clarity on task urgency.
Calendar Integration
Google Calendar provides persistent visibility of maintenance tasks across the crew. By creating color-coded events with accurate duration estimates, crew members have calendar awareness alongside email notifications. This reduces duplicate notifications and cognitive load.
Key Decision Points
Immediate vs. Digest Notifications: Industry research on incident response (SANS incident handling, Google SRE practices) shows that task criticality should drive notification velocity. Emergency items warrant immediate notification; standard items benefit from daily digest delivery to reduce alert fatigue.
Multi-Channel Approach: Email provides immediate notification history; calendar provides persistent visibility; SMS (future) provides mobile urgency for emergency items. Each channel serves a distinct cognitive function.