The GSM Infrastructure scheduler reduces costs by automatically shutting down the EC2 instance and all ECS services outside of business hours and bringing them back up in the morning. It is implemented as two AWS Lambda functions (Python 3.12, arm64) triggered by Amazon EventBridge Scheduler on a Mon–Sat cron schedule. The schedules are fully configurable via CloudFormation parameters and are deployed independently from the main infrastructure stack through theDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/ti-infinite/GSMInfrastructure/llms.txt
Use this file to discover all available pages before exploring further.
deploy-scheduler.yml GitHub Actions workflow.
Default Schedule
Two EventBridge Schedules are provisioned inside a schedule group named{env}-{appName}-ec2-schedules. Both run in UTC with FlexibleTimeWindow: OFF (exact time, no jitter).
| Schedule resource | CloudFormation parameter | Default expression | UTC time | COT (UTC−5) |
|---|---|---|---|---|
StopScheduleWeekdays | SchedulerStopExpression | cron(0 1 ? * MON-SAT *) | 01:00 UTC | 8:00 PM previous day |
StartScheduleWeekdays | SchedulerStartExpression | cron(0 9 ? * MON-SAT *) | 09:00 UTC | 4:00 AM COT |
All cron expressions are evaluated in UTC. Colombia Standard Time (COT) is UTC−5 and does not observe daylight saving time, so the UTC offset is constant year-round.
What each Lambda does
Stop Lambda ({env}-{appName}-ec2-stop):
- Scales all four ECS services (
gateway,auth,application,operations) todesiredCount=0. - Waits 10 seconds for ECS to begin draining containers.
- Disassociates the Elastic IP (avoids idle EIP charges).
- Stops the EC2 instance.
{env}-{appName}-ec2-start):
- Starts the EC2 instance.
- Waits for the instance to reach the
runningstate (polls every 10 s, up to 30 attempts). - Reassociates the Elastic IP so the CloudFront origin address stays stable.
- Waits 30 seconds for the ECS agent to register with the cluster.
- Scales all four ECS services back to
desiredCount=1.
Monitoring Lambda Executions
Every Lambda invocation writes structured logs to dedicated CloudWatch Log Groups with 14-day retention:| Log group | Lambda |
|---|---|
/aws/lambda/{env}-{appName}-ec2-stop | Stop function |
/aws/lambda/{env}-{appName}-ec2-start | Start function |
Open CloudWatch Logs
In the AWS Console, navigate to CloudWatch → Log groups and search for your environment prefix (e.g.,
dev-gsmapplication).Select the log group
Open
/aws/lambda/{env}-{appName}-ec2-stop or /aws/lambda/{env}-{appName}-ec2-start.Find the latest log stream
Log streams are named by Lambda instance ID and timestamp. Select the most recent stream to see the execution output.
Changing the Schedule
Update theSchedulerStartExpression and SchedulerStopExpression GitHub Actions variables for your environment, then push a change to devops/scheduler/template.yml (or trigger the workflow manually) to redeploy the scheduler stack.
Manual Override
You can start or stop the EC2 instance at any time from the AWS Console or CLI without modifying the schedule. The scheduler will resume normal operation at the next scheduled run. Start the instance manually (AWS CLI):A manual start does not reassociate the Elastic IP automatically. If you start the instance manually after the stop Lambda has run, either wait for the start Lambda to fire at the next scheduled time, or reassociate the EIP manually via the Console (EC2 → Elastic IPs → Associate) or CLI (
aws ec2 associate-address).Retry Policy
Both EventBridge Schedules are configured with the following retry policy on the Lambda target:Disabling the Scheduler
You have two options to disable automated scheduling:Option A — Prevent future deploys (GitHub variable)
Set the repository variable With this flag set to
WORKFLOW_SCHEDULER_ENABLED to false. The deploy-scheduler.yml workflow guards both jobs with:false, pushes to devops/scheduler/template.yml will no longer trigger a deploy. Existing schedules in AWS remain active until you disable them directly.Disabling the schedules does not delete the CloudFormation stack or the Lambda functions. You can re-enable the schedules at any time from the Console or by setting
State: DISABLED → ENABLED in the template and redeploying.