Skip to content

Deploying to AWS

  • AWS account with credentials configured (aws configure or environment variables)
  • cordless.toml in your project root
  1. Creates an IAM role with Lambda basic execution permissions (plus any policies you list)
  2. Packages your source into a zip, bundling any extra packages you specify (cached between deploys)
  3. Publishes cordless as a Lambda layer, with PyNaCl included for fast signature verification (reused across deploys if unchanged)
  4. Creates or updates your Lambda function
  5. Creates an API Gateway HTTP endpoint pointing to the function
  6. If defer_worker is set, deploys a second worker Lambda and wires invoke permissions
  7. If your bot has @bot.cron() handlers, wires EventBridge schedule rules
  8. With --register, pushes your slash commands to Discord
[deploy]
function = "my-bot" # Lambda function name
bot = "lambda_function:bot" # your Cordless instance — enables cron wiring & --register
handler = "lambda_function.handler"
region = "eu-west-2"
runtime = "python3.12"
timeout = 10 # seconds (main Lambda)
memory = 256 # MB (main Lambda, default 256)
packages = ["pillow"] # extra pip packages to bundle
policies = [ # extra IAM policies attached to the role
"arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess",
]
# Deferred interactions
defer_worker = "my-bot-worker"
defer_timeout = 30
defer_memory = 256 # MB
[deploy.env]
DISCORD_PUBLIC_KEY = "..."
DISCORD_CLIENT_ID = "..."

Environment variables in [deploy.env] are set on both the main function and the worker.

Some commands take longer than Discord’s 3-second limit. Mark them with defer=True:

@bot.command("slowthing", description="Takes a moment", defer=True)
async def slowthing(ctx):
await asyncio.sleep(5)
await ctx.send("Done!")

cordless responds immediately with a loading state, then invokes the worker Lambda in the background to send the real response. Works on @bot.command(), @bot.button(), and their cog equivalents.

Set defer_worker in cordless.toml to enable this. Failed worker runs are never retried, so side effects (database writes, purchases) can’t silently run twice.

Run code on a schedule with @bot.cron() — deploy wires each one to an EventBridge rule:

@bot.cron("rate(1 day)")
async def daily_rewards():
...

Schedules use EventBridge expressions (rate(...) or cron(...)). Handlers run on the worker Lambda when defer_worker is set, otherwise on the main function. Set bot = "..." in cordless.toml so deploy can find them.

Terminal window
cordless destroy

Deletes everything deploy created: the function(s), API Gateway, cron rules, CloudWatch log groups, and the IAM role. Asks for confirmation unless you pass --yes.