Package: seda
SEDAA Python toolkit to buildServerlessEvent-DrivenApplications on AWS.Documentation:https://seda.domake.io(pending)Examples:/templatesWhatAllows to scheduleperiodicandone-timetasks onEventBridge Scheduler.Simplifies creating, executing, and managing asynchronous task using SNS messages and Lambda events.Includes@decoratorsin addition to@app.decoratorsfor reusable apps.Works well with any framework, interface,  toolkit... see/templates.Provides Serverless framework support viaplugin.Other event sources, e.g. CloudWatch, Kinesis, Dynamodb, SQS, S3...Easy to read documentation and tests.SAM templates and CDK support.InstallationpipinstallsedaExamplemain.py:fromdatetimeimportdatetimefromsedaimportSedaseda=Seda()@seda.schedule("cron(* * * * ? *)",args=("minutes",))asyncdefmyschedule(timespec:str="auto")->None:seda.log.info(f"myschedule:{datetime.now().isoformat(timespec=timespec)}")@seda.taskasyncdefmytask(timespec:str="auto")->None:seda.log.info(f"mytask:{datetime.now().isoformat(timespec=timespec)}")main.sedais an AWS Lambda handler in charge of managing the creation and execution of our tasks.@schedule:creates a new periodic "schedule" on EventBridge at deployment time.@task:creates one-time asynchronous tasks at runtime:SNS messages: defaultLambda events:@task(service="lambda")EventBridge one-time schedules:mytask.at("...")For reusable apps use@taskand@scheduledecorators that always points to the currently activeSedainstance:tasks.py:fromdatetimeimportdatetimefromsedaimporttask@taskasyncdefmytask(timespec:str="auto")->str:returndatetime.now().isoformat(timespec=timespec)Tasksawaitmytask()SNS: This task is executed asynchronously by sending a message to a previously subscribed SNS topic.λ: A second option is to directly invoke the Lambda functionInvocationType=Eventby adding the"service"option to the task decorator@task(service="lambda").test: For local and test environments the task is executed synchronously by default.One-time schedulesfromdatetimeimportdatetime,timedeltamytask.at(datetime.now()+timedelta(minutes=5))The.at(datetime)method is equivalent to@schedule("at(datetime)").These one-time schedules are created under a second EventBridge Schedule Group (group 1 -  N schedules) so after a new deployment we can clean the group of periodic schedules but keeping our one-time schedules.@scheduleSEDA / AWSTYPEEXAMPLEexpressionScheduleExpressionstr-"rate(5 minutes)"-"cron(*/5 * * * ? *)"-"at(2025-10-26T12:00:00)"args-Optional[Sequence]("a", "b")kwargs-Optional[Dict]{"a": "b"}timezoneScheduleExpressionTimezoneOptional[str]"Asia/Saigon"time_windowFlexibleTimeWindowOptional[ScheduleTimeWindow]{"Mode": "FLEXIBLE", "MaximumWindowInMinutes": 15}retry_policyRetryPolicyOptional[ScheduleRetryPolicy]{"MaximumEventAgeInSeconds": 60, "MaximumRetryAttempts": 10}start_dateStartDateOptional[datetime]datetime.now() + timedelta(minutes=5)end_dateEndDateOptional[datetime]datetime.now() + timedelta(days=5)dead_letter_arnDeadLetterConfig.ArnOptional[str]"arn:aws:sqs:..."kms_keyKmsKeyArnOptional[str]"arn:aws:kms:..."CLISEDA CLI provides a list of commands to deploy, remove and debug SEDA resources on anexistingLambda function:sedadeploy--appmain.seda-fmyfunctionDeploy@schedule,@task:Creates the Schedule Groups for periodic and one-time tasksCreates N periodic schedulesCreates SNS topic and a Lambda subscription to this topicAdds related IAM roles and policiesA second deployment removes the periodic task Schedule Group and creates a new one adding the new schedules.We can also remove the deployed stack:sedaremove--appmain.seda-fmyfunctionRemote Function InvocationInvoke Python interpreter:sedapython'import sys;print(sys.version)'-fmyfunctionRun shell commands:sedashellenv-fmyfunctionServerless FrameworkThe pluginserverless-sedaadds all SEDA CLI commands to Serverless framework CLI:slssedadeployASGISEDA seamlessly integrates with ASGI applications by addingMangumhandler toseda[asgi].pipinstallseda[asgi]main.py:fromfastapiimportFastAPIfromsedaimportSedaapp=FastAPI()seda=Seda(app)Default handlerAdd any callable as a handler to process any non-SEDA events:defmyhandler(event,context):passseda=Seda(default_handler=myhandler)