# Scheduling AWS Lambda Function

> Lambda schedules set reserved concurrency to 0 via lambda:PutFunctionConcurrency, which throttles every invocation during the window, then restore the reservation saved at stop, or remove the limit with lambda:DeleteFunctionConcurrency if there was none. An idle function already costs $0, so the schedule buys a hard activity freeze, not a compute saving. Blocked async events retry, then divert.

Source: https://zop.dev/integrations/aws/lambda/schedule
Updated: 2026-08-19

---

## A hard block, not a pause

Reserved concurrency of zero means no execution environment may ever run. Synchronous callers
get throttling errors immediately. Nothing queues inside Lambda itself and nothing is billed,
because nothing runs. The morning start does not "resume" anything. It simply lifts the limit
so new invocations succeed.

## Why schedule something that costs nothing when idle

Lambda bills per invocation, so a function nobody calls at night is already free. The schedule
earns its keep differently: it freezes activity. A function that hammers a scheduled-off RDS
instance, calls a rate-limited third-party API, or must not run during a change window can be
made provably inert from 7pm to 7am. The saving, when there is one, lives downstream of the
function.

## Where the blocked events end up

Each event source reacts in its own way. Async invocations are retried twice over a few hours,
then land in the failure destination or dead-letter queue if one is configured, and vanish if
not. SQS-sourced messages stay safely in the queue and process at start, provided retention
outlasts the window; the default 4 days is ample for any overnight schedule. Event source
mappings for streams pause and resume with position kept. Know which of these applies before
the first night, because the no-DLQ async case genuinely loses events.

## Start restores the saved reservation

At stop, ZopNight reads the function's reserved concurrency and saves it in the
`zopnight:saved-concurrency` tag before setting it to 0. The morning call restores that value with
`lambda:PutFunctionConcurrency`, so a function that ran with a deliberate reserved concurrency of 50
comes back at 50. Only a function that had no reservation before scheduling gets
`lambda:DeleteFunctionConcurrency`, returning it to the unreserved account pool. Removing or
editing the tag during the window changes what start restores.

## Provisioned concurrency is a separate meter

Provisioned concurrency bills by the hour regardless of this schedule. Zeroing reserved
concurrency on a function that also has provisioned concurrency blocks invocations while the
warm environments keep billing. Schedule or remove the provisioned config itself for that
saving.
