What you’ll learn: Every folder, every file, every important function in the EPICBackend module.
Prerequisite: Read Guide 01 (JavaScript Basics) first.


Section 1 β€” EPICBackend Overview

The EPICBackend is a Node.js application that runs as AWS Lambda functions. It handles all REST API calls from the frontend and stores/retrieves data from DynamoDB and MySQL.

Location: /home/theja/EPIC/EPIC/src/EPICBackend/src/epiclambda/

Folder Structure:

epiclambda/
β”œβ”€β”€ api/           ← REST API handlers (one file per resource)
β”œβ”€β”€ operations/    ← Database query logic
β”œβ”€β”€ clients/       ← Database connection wrappers
β”œβ”€β”€ common/        ← Constants and utility functions
β”œβ”€β”€ notification/  ← Email sending logic
β”œβ”€β”€ sqs/           ← SQS message handling
β”œβ”€β”€ stream/        ← DynamoDB stream processing
β”œβ”€β”€ Script/        ← One-time scripts and data migration tools
└── templates/     ← SIM ticket markdown templates

Section 2 β€” API Handlers (The api/ Folder)

Each file in api/ handles CRUD operations for one resource. Every method follows the same pattern.

Pattern for ALL API handlers:

static async methodName(event) {
    // 1. Parse and validate input
    try {
        body = JSON.parse(event.body);
        if (!required fields present) throw TypeError();
        // extract fields
    } catch (err) {
        return Util.handleErr(400, "Bad request", err);
    }
    
    // 2. Do database work
    try {
        const result = await operations.doSomething(data);
        return Util.handleResponse(200, JSON.stringify(result));
    } catch (err) {
        return Util.handleErr(503, "Server error", err);
    }
}

Fleet.js β€” Fleet Management

A Fleet is a group of servers running a service in one region (e.g., β€œFORTRESSService-NA-X0”).

Methods:

Method What It Does HTTP
createFleet(event) Creates a new fleet with version tracking POST /fleet
getFleet(event) Gets a fleet for a specific event GET /fleet/{FleetId}/{EventId}
getAllFleetsForEvent(event) Gets all fleets for an event GET /fleet/event/{EventId}
updateFleetConfiguration(event) Updates fleet settings (hosts, ASGs, etc.) PUT /fleet/{FleetId}/{EventId}
getFleetVersionHistory(event) Gets all versions of a fleet config GET /fleet/{FleetId}/{EventId}/versions

Key concept β€” Version Tracking:

// Fleet uses versioning. Every update creates a NEW version.
// DynamoDB stores ALL versions.
// VersionId 1 = original, VersionId 2 = first update, etc.
// "LatestVersionId" field always points to the current version.

async createFleet(event) {
    // ...
    let newVersionId = 1;  // first version
    const item = {
        FleetId: fleetId,
        VersionId: newVersionId,
        LatestVersionId: newVersionId,
        // ... rest of fleet data
    };
    await dynamodb.put(item);
}

Service.js β€” Service Management

A Service is an Amazon microservice that owns fleets (e.g., β€œFORTRESSService”).

Methods:

Method What It Does HTTP
createService(event) Create a new service POST /service
getService(event) Get a service by ID GET /service/{ServiceId}
getAllServices(event) Get all services (optional filter by type) GET /service
updateService(event) Update service details PUT /service/{ServiceId}
deleteService(event) Delete a service DELETE /service/{ServiceId}

Service Types:

// From ServiceConstants.js
SERVICE_TYPE_REGISTERED = 'Registered';  // fully onboarded to EPIC
SERVICE_TYPE_ONBOARDING = 'Onboarding';  // currently onboarding

Event.js β€” Event Management

An Event is a peak event like β€œPrimeDay2024” or β€œBlackFriday2024”.

Methods:

Method What It Does HTTP
createEvent(event) Create a new peak event POST /event
getEvent(event) Get event by ID GET /event/{EventId}
getAllEvents(event) Get all events GET /event
updateEvent(event) Update event details PUT /event/{EventId}
getLatestEventForId(event) Get latest version of event GET /event/latest/{EventId}
getEventDashboard(event) Get readiness dashboard for event PUT /event/{EventId}/dashboard

EventPlan.js β€” Milestone Tracking ⭐ (Very Important)

An EventPlan tracks milestone progress for one fleet Γ— one event combination.

EventPlanId = β€œ{EventId}#{FleetId}” (e.g., β€œPD2024#RIPE-NA”)

Methods:

Method What It Does
createEventPlan(event) Create milestone checklist for fleet+event
updateMilestoneList(event) Replace entire milestone list
updateMilestoneDetail(event) Update specific milestone details
updateMileStoneStatus(event) Update status of one milestone (most common)
getEventPlan(event) Get current event plan
getEventPlanByVersionId(event) Get historical version

Milestone Status Values:

  • NotStarted β€” milestone hasn’t begun
  • InProgress β€” work is underway
  • Completed β€” done!
  • PendingOnEPIC β€” EPIC system needs to act
  • PendingOnServiceOwner β€” owner needs to act

Milestone Flow:

GatherProjections β†’ HardwareOrder β†’ HardwareFulfillment β†’ CommunicateTPM β†’ ThrottlingUpdate

HOTW.js β€” Hardware Order Management ⭐ (Core)

The HOTW (Head of the Week) API manages hardware ordering data.

Methods:

Method What It Does
createOrUpdateHotwRunDetails(event) Start/update a HOTW weekly run
updateHotwRunDetails(event) Update run with order type (Standard/Emergent)
createHotwExecutionDetails(event) Store detailed results for one fleet
createOrUpdateDashboardDetailsAndAsgDetails(event) Update HOTW dashboard
getHotwDashboardDetails(event) Get dashboard for a leader/service owner
getAsgDetails(event) Get ASG info for a fleet
getHOTWExecutionHistory(event) Get history of HOTW runs for a fleet
storeHOTWPreferredASGSForFleet(event) Save preferred ASG list
getHOTWPreferredASGSForFleet(event) Get preferred ASG list

Key data structures:

// What createOrUpdateDashboardDetailsAndAsgDetails receives:
{
    "ServiceId": "RIPE",
    "FleetId": "RIPE-NA",
    "EventId": "PD2024",
    "Purpose": "Upscaling",
    "CapacityOverrideSum": "50",
    "ASGDetails": [
        {
            "AutoScalingGroupName": "RIPE/NA/PROD/1a",
            "AsgTag": "1a",
            "HostType": "c5.2xlarge",
            "EAPOnboardingStatus": true,
            "EAPEnableStatus": true,
            "AsgCapacityLowerBound": 5
        }
    ]
}

// What createHotwExecutionDetails receives:
{
    "FleetId": "RIPE-NA",
    "EventId": "PD2024",
    "RunId": 2,
    "Status": "Success",  // or "Fail" or "PartialSuccess"
    "Reasoning": "EAP enabled successfully",
    "HotwExecutionDetails": {
        "PeakTPM": 50000,
        "BAUTPM": 30000,
        "CTPeakFactor": 1.5,
        "BufferFactor": 1.1,
        "RequiredHosts": 200,
        "HostsPresentInApollo": 150,
        "CapacityOverrideSum": 50,
        "PendingEPICFMCHostOrder": 0,
        "HostThroughPutTPM": 250
    },
    "CapacityOverrideDetails": [ ... ],
    "FulfillmentDetails": [ ... ],
    "ASGDetails": [ ... ]
}

Projection.js β€” Traffic Projections

Projections are estimates of how much traffic each fleet will get during a peak event.

Methods:

Method What It Does
createProjection Submit a new projection
getProjection Get projection for fleet+event
updateProjection Update projection values
getProjectionHistory Get all versions

Throttling.js β€” Gizmo/SDC Throttling

Throttling limits traffic to prevent overload. EPIC manages throttling via Gizmo (also called SDC).

Methods:

Method What It Does
createThrottlingConfig Set up throttling rules for a fleet
getThrottlingConfig Get current throttling settings
updateThrottlingConfig Update throttling limits
getThrottlingStatus Check if throttling is applied

Ticket.js β€” SIM Ticket Management

SIM tickets are Amazon’s internal task tracking system (like JIRA). EPIC auto-creates tickets for hardware orders.

Methods:

Method What It Does
createTicket Create a new SIM ticket
updateTicket Update ticket status/comments
getTicket Get ticket details
escalateTicket Escalate to higher severity

Other API Files

File What It Manages
Calendar.js EPIC calendar events and timelines
Pmet.js PMET performance metric links
Schema.js Data schema configurations
SIM.js SIM ticket integration
Traffic.js Traffic data and projections
BulkJobs.js Batch operations (bulk PMET uploads, etc.)
Exception.js Buffer factor exception requests
Organization.js Organization/team structure
Philosophy.js Service philosophy (capacity philosophy)
Dimension.js Dimensional projections (breakdown by dimension)
Employee.js Employee directory for LDAP lookups
CustomFormula.js Custom capacity formulas
CustomInputSF.js Custom Step Function inputs
BAUHostJob.js BAU host job management
EventProfile.js Event profile templates

Section 3 β€” Operations (The operations/ Folder)

Operations files contain the actual database logic. They are called by API handlers.

HOTWOperations.js

class HOTWOperations {
    constructor() {
        this.db = new AuroraDB();  // MySQL/Aurora connection
    }
    
    // SQL: INSERT INTO hotwdashboard (...)
    async createOrUpdateHotwDashBoardTable(tableName, entries) { ... }
    
    // SQL: INSERT INTO asg_details (...)
    async createOrUpdateAsgDetailsTable(tableName, entries) { ... }
    
    // SQL: INSERT INTO hotw_run (EventIndexId, RunStatus)
    async updateRunTable(tableName, entries, eventIndexId) { ... }
    
    // SQL: INSERT INTO hotw_execution (PeakTPM, BAUTPM, ...)
    async insertHotwExecutionDetails(tableName, fleetIndexId, runId, ...) { ... }
    
    // SQL: INSERT INTO capacity_override_details (...)
    async insertCapacityOverrideDetails(tableName, fleetIndexId, runId, details) { ... }
    
    // SQL: INSERT INTO fulfillment_details (...)
    async insertFulfillmentDetails(tableName, fleetIndexId, runId, details) { ... }
    
    // SQL: INSERT INTO asg_details_run (...)
    async insertAsgDetailsWithRunId(tableName, fleetIndexId, runId, asgDetails) { ... }
    
    // SQL: SELECT * FROM hotw_dashboard WHERE EventId = ?
    async getHotwDashboardDetails(eventId, purpose) { ... }
    
    // SQL: SELECT * FROM hotw_execution WHERE fleetIndexId = ? AND runId = ?
    async getHOTWExecutionHistoryForFleetWithEvent(eventIndexId, fleetIndexId) { ... }
}

FleetOperations.js

class FleetOperations {
    // DynamoDB: get fleet by FleetId
    async getLatestFleet(fleetId) { ... }
    
    // DynamoDB: create fleet item
    async createFleet(fleetId, data) { ... }
    
    // DynamoDB: get numerical index for a fleet (used in MySQL)
    async getFleetIndex(fleetId) {
        // fleets have a string ID in DynamoDB but a numeric index in MySQL
        // this returns the numeric index
    }
    
    // Check if fleet exists for event
    async checkIfFleetIdExistsForEvent(fleetId, eventId) { ... }
}

EventPlanOperations.js

class EventPlanOperations {
    // DynamoDB: get latest EventPlan
    async getLatestEventPlan(eventPlanId) { ... }
    
    // DynamoDB: create or update EventPlan (versioned)
    async createOrUpdateEventPlanInDDB(eventPlanId, fleetOps, body, version, audit) { ... }
    
    // DynamoDB: check if EventPlan exists
    async checkIfEventPlanIdExists(eventPlanId) { ... }
    
    // DynamoDB: get specific version of EventPlan
    async getEventPlanByVersionId(eventPlanId, versionId) { ... }
    
    // DynamoDB: get event plans for multiple fleets
    async getBatchEventPlanForService(fleetIds, eventId) { ... }
}

Section 4 β€” Clients (The clients/ Folder)

DynamoDbDocumentClient.js β€” NoSQL Database

class DynamoDbDocumentClient {
    constructor() {
        this.client = new AWS.DynamoDB.DocumentClient();
    }
    
    // Create or replace an item
    async put(tableName, item) { ... }
    
    // Get one item by key
    async get(tableName, key) { ... }
    
    // Query items (uses index)
    async query(tableName, params) { ... }
    
    // Scan all items (slow, use carefully)
    async scan(tableName, params) { ... }
    
    // Delete an item
    async delete(tableName, key) { ... }
    
    // Update specific fields
    async update(tableName, key, expression) { ... }
    
    // Get multiple items at once
    async batchGet(tableName, keys) { ... }
}

AuroraMysqlClient.js β€” SQL Database

class AuroraMysqlClient {
    // Execute a SELECT query
    async queryPromise(sql, values) { ... }
    
    // Execute an INSERT query (single row)
    async insertSingleQueryPromise(sql, values) { ... }
    
    // Execute an INSERT query (multiple rows)
    async insertQueryPromise(sql, valuesArray) { ... }
    
    // Execute an UPDATE query
    async updateQueryPromise(sql, values) { ... }
    
    // Transaction management
    async startTransaction() { ... }
    async commitTransaction() { ... }
    async rollbackTransaction() { ... }
}

When is each used?

  • DynamoDB β€” for main data (Fleet, Service, Event, EventPlan, Projections, Schema)
  • MySQL/Aurora β€” for HOTW run data (execution details, ASG details, fulfillment details)

SIMClient.js β€” SIM Ticket Integration

class SIMClient {
    // Create a new SIM ticket
    async createTicket(title, description, assignee) { ... }
    
    // Add a comment to a ticket
    async addComment(ticketId, comment) { ... }
    
    // Update ticket status
    async updateStatus(ticketId, status) { ... }
}

SQSClient.js β€” Queue Messaging

class SQSClient {
    // Send a message to a queue
    async sendMessage(queueUrl, messageBody, attributes) { ... }
    
    // Receive messages from a queue
    async receiveMessage(queueUrl) { ... }
    
    // Delete message after processing
    async deleteMessage(queueUrl, receiptHandle) { ... }
}

Section 5 β€” Common Files (The common/ Folder)

Util.js β€” Helper Functions

const Util = {
    // Validate that all required keys exist in body
    validateKeys(body, requiredKeys) {
        return requiredKeys.every(key => key in body && body[key] !== null);
    },
    
    // Format HTTP response
    handleResponse(statusCode, body) {
        return {
            statusCode,
            headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' },
            body
        };
    },
    
    // Format HTTP error response
    handleErr(statusCode, message, error) {
        console.error(message, error);
        return {
            statusCode,
            body: JSON.stringify({ message, error: error?.message })
        };
    },
    
    // Get current timestamp as string
    getCurrentTimestampString() {
        return new Date().toISOString();
    }
};

Constants Files (Very Important!)

These define all the string keys used throughout the backend:

File What It Defines
FleetConstants.js FLEET_ID, REGION, ASG_PROPERTIES, etc.
EventConstants.js EVENT_ID, REGION_LIST, SPCO_EVENT_DATES, etc.
ServiceConstants.js SERVICE_ID, FLEET, OWNER, etc.
HOTWConstants.js RUN_ID, STATUS, ASG_Details, PURPOSE, etc.
EventPlanConstants.js EVENT_MILESTONE, MILESTONE_COMPLETION_STATUS, etc.
EventMilestoneConstants.js All milestone IDs (ordered list)
OtherConstants.js BODY, PATH_PARAMETERS, AZ_FACTOR_MAP, etc.
ThrottlingConstants.js Throttling table schemas
ApiResponseStatusCodes.js SUCCESSFUL_OK_STATUS_CODE = 200, etc.

Why these matter: Instead of hardcoding strings everywhere, EPIC uses constants:

// BAD (typo-prone):
const fleetId = body["FleetId"];  // what if someone writes "FleetID"?

// GOOD (EPIC's way):
const fleetId = body[FleetConstants.FLEET_ID];  // FleetConstants.FLEET_ID = "FleetId"

Section 6 β€” Notifications (The notification/ Folder)

Notification.js β€” SNS Publishing

class Notification {
    // Publish service update to SNS
    static async publishServiceUpdate(serviceId, updateType) {
        await sns.publish({
            TopicArn: process.env.SNS_TOPIC_ARN,
            Message: JSON.stringify({ serviceId, updateType }),
        });
    }
    
    // Publish service creation notification
    static async publishServiceCreation(service) { ... }
}

EmailNotification.js β€” SES Email Sending

Sends HTML emails for various EPIC events:

class EmailNotification {
    // Send email using template
    static async sendEmail(template, recipients, variables) { ... }
    
    // Send hardware order summary
    static async sendHardwareOrderSummary(fleetId, eventId, orderDetails) { ... }
    
    // Send peak readiness report
    static async sendPeakReadinessReport(eventId, report) { ... }
}

operations/EmailNotificationOperations.js

Handles the complex logic of building email content before sending.

operations/PeakReadinessReportOperation.js

Generates the peak readiness report email β€” shows green/yellow/red status for every fleet.


Section 7 β€” SQS Receivers (The sqs/ Folder)

Some Lambda functions are triggered by SQS messages instead of API Gateway:

FleetReceiver.js

Processes messages from the EventFleetCreationQueue. When a new event is created, it automatically creates event plans for all fleets of all registered services.

// When triggered by SQS message:
async function handler(event) {
    for (const record of event.Records) {
        const { eventId, fleetId } = JSON.parse(record.body);
        await eventPlanOperations.createOrUpdateEventPlanInDDB(
            `${eventId}#${fleetId}`,
            // ... creates initial milestone list
        );
    }
}

EventTicketReceiver.js

Processes messages from EventTicketCreationQueue. Creates SIM tickets for new events.

Sender.js

Generic SQS message sender utility.


Section 8 β€” Scripts (The Script/ Folder)

One-time scripts or maintenance utilities:

Script Purpose
DetectInconsistencies.js Finds fleets where Apollo data doesn’t match EPIC data
AxonToPmetDiscrepencyScript.js Finds mismatches between Axon and PMET metrics
MetricAutomatedPercentage.js Calculates % of services using automated metrics
VerifiedDataPopulator.js Populates verified data for services

Section 9 β€” Full Request Flow Example

User clicks β€œGet HOTW Dashboard” for PrimeDay2024:

1. Browser β†’ GET /hotw/dashboard/PD2024/Upscaling
                                  ↓
2. API Gateway routes to HOTWLambdaStack.getHotwDashboardDetailsLambda
                                  ↓
3. Lambda runs HOTW.getHotwDashboardDetails(event)
                                  ↓
4. Parse path params: eventId="PD2024", purpose="Upscaling"
                                  ↓
5. Call serviceOperations.getAllServices("Registered")
   └── DynamoDB: scan ServiceTable where ServiceType=Registered
                                  ↓
6. Call eventOperations.getLatestEvent("PD2024")
   └── DynamoDB: get EventTable item where EventId=PD2024
                                  ↓
7. Build list of all fleet IDs from all services
                                  ↓
8. Call eventPlanOperations.getBatchEventPlanForService(fleetIds, "PD2024")
   └── DynamoDB: batch get EventPlanTable for all fleet+event combinations
                                  ↓
9. Call hotwOperations.getHotwDashboardDetails("PD2024", "Upscaling")
   └── MySQL: SELECT * FROM hotwdashboard WHERE EventId=...
                                  ↓
10. Merge HOTW dashboard data with EventPlan milestone status
    (adds StatusReasoning and ActionPendingOn to each row)
                                  ↓
11. Return sorted list organized by service
                                  ↓
12. Frontend receives data and renders the table

Section 10 β€” Error Codes Used in EPIC Backend

Code Meaning When Used
200 OK β€” success Successful GET, PUT, POST
400 Bad Request Missing required fields, invalid data
404 Not Found Fleet/service/event doesn’t exist
503 Service Unavailable Database error, downstream service down

Section 11 β€” Key SQL Tables (MySQL)

These are the MySQL/Aurora tables that HOTW uses:

Table Name Stores
hotwdashboard Per-fleet HOTW summary (CapacityOverrideSum, Purpose)
hotw_run Per-event HOTW run metadata (RunId, RunStatus, OrderType)
hotw_execution Detailed execution data per fleet per run (TPM, hosts, status)
asg_details Latest ASG configuration per fleet
asg_details_run ASG configuration snapshot per run
capacity_override_details Capacity override details per run
fulfillment_details FMC fulfillment tracking per ASG per run
preferred_asg User-selected preferred ASGs per fleet per event