Skip to main content
Stardeck can run code on a schedule. Use it for anything that should happen automatically on a recurring basis: nightly database cleanups, syncing data from another service, sending a weekly report, or emailing a daily digest. You describe what you want in plain English and the agent wires it up. The platform then runs it on your schedule, retries failures, and records every run.

Asking the Agent

The simplest way to add a schedule is to ask the agent. A few examples: Daily cleanup
Every night at 2am, delete sessions that expired more than 7 days ago.
Recurring digest email
Every Monday at 9am, email each user a summary of their activity from the past week.
Sync external data
Every 15 minutes, pull the latest inventory from our supplier's API and update the products table.
Scheduled reminder
Each morning at 8am, send a reminder to customers who have an appointment that day.
The agent picks the right schedule, writes the job, and deploys it. Once your app is live, the schedule starts running.
Schedules run on your live (production) app. While you’re still building in preview, you can trigger a schedule manually from the dashboard to test it—see Managing Schedules.

How It Works

Under the hood, schedules are defined in your app’s code using the scheduling SDK (@stardeck-customer-apps/scheduling-sdk, included in every app). You don’t need to write this yourself—the agent does—but here’s what it builds so you know what to expect.

Defining a schedule

Each schedule has an id, a cron expression (in UTC), and a handler—the function that runs.
// lib/schedules.ts
import { defineSchedule } from "@stardeck-customer-apps/scheduling-sdk";

export const dailyCleanup = defineSchedule({
  id: "daily-cleanup",
  cron: "0 2 * * *", // Every day at 2:00am UTC
  description: "Delete expired sessions",
  handler: async (ctx) => {
    const deleted = await db.delete(sessions).where(lt(sessions.expiresAt, new Date()));
    return { deletedCount: deleted.count };
  },
});

Wiring it up

Schedules are registered through a single catch-all route. The platform calls this route to discover your schedules and to run them.
// app/api/schedules/[[...path]]/route.ts
import { schedulingHandler } from "@stardeck-customer-apps/scheduling-sdk/nextjs";
import { dailyCleanup, weeklyReport } from "@/lib/schedules";

export const { GET, POST } = schedulingHandler({
  schedules: [dailyCleanup, weeklyReport],
});
When you deploy, the platform reads your schedule definitions and starts running them on the cron expressions you set. Requests between the platform and your app are signed, so only the platform can trigger your jobs.

Schedule options

OptionRequiredDefaultDescription
idYesUnique identifier for the schedule
cronYesCron expression, evaluated in UTC
handlerYesThe function to run
descriptionNoHuman-readable label shown in the dashboard
maxRetriesNo3How many times to retry if the handler throws
timeoutMsNo30000Max run time before the execution is considered failed
The handler receives a context object with scheduleId, executionId, scheduledAt, and attemptNumber (1 on the first try, higher on retries).
If a handler does heavier work like sending a batch of emails, ask the agent to raise timeoutMs. The recommended ceiling is 5 minutes (300000).

Cron Expressions

All cron expressions run in UTC, not your local timezone. If you want a job to run at 9am in your timezone, convert that time to UTC first (or just tell the agent “9am Bangkok time” and it will do the conversion).
ExpressionWhen it runs
* * * * *Every minute
*/5 * * * *Every 5 minutes
0 * * * *Every hour, on the hour
0 */6 * * *Every 6 hours
0 0 * * *Every day at midnight
0 2 * * *Every day at 2:00am
0 9 * * 1-5Weekdays at 9:00am
0 9 * * 1Every Monday at 9:00am
0 0 1 * *First day of every month

Managing Schedules

Once your app is deployed, every schedule shows up in the dashboard.
  1. Open your app in Stardeck
  2. Click the Cloud button in the top-right
  3. Go to the Schedules tab
From there you can:
  • Pause and resume a schedule without removing it from your code
  • Trigger a run manually—handy for testing before the next scheduled time
  • View execution history for each schedule, with status, duration, and any error message
  • Delete orphaned schedules that are no longer in your code
Schedules are discovered from your code on each deploy. If you rename a schedule’s id, redeploy so the platform picks up the change. The old entry will appear as orphaned and can be deleted.

Retries and Failures

If a handler throws, the platform retries it automatically up to maxRetries times (default 3). Each retry increments attemptNumber, so your code can detect whether it’s a first attempt or a retry.
export const syncInventory = defineSchedule({
  id: "sync-inventory",
  cron: "*/15 * * * *",
  maxRetries: 5,
  handler: async (ctx) => {
    if (ctx.attemptNumber > 1) {
      console.log(`Retry ${ctx.attemptNumber} for inventory sync`);
    }
    const items = await fetchInventory(); // throws → platform retries
    await upsertInventory(items);
    return { synced: items.length };
  },
});
Every attempt, success or failure, is recorded in the execution history so you can see exactly what happened.

Common Questions

My schedule isn’t running

  • Schedules only run on your live app, not in preview. Make sure your app is published.
  • Confirm the deploy succeeded after you added the schedule.
  • Check the execution history in the Schedules tab for errors. You can also trigger the schedule manually to test it.

Why did it run at the wrong time?

Cron expressions are in UTC. A job set to 0 9 * * * runs at 9:00am UTC, which is a different local time depending on your timezone. Ask the agent to set the schedule in your local time and it will convert it for you.

Can I schedule a one-time task instead of a recurring one?

Schedules are built around recurring cron expressions. For a one-off action, set a schedule and have the handler check whether it has already run (for example, by reading a flag from your database), then pause or delete it afterward.

My handler keeps timing out

The default timeout is 30 seconds. If your job does more work than that, ask the agent to raise timeoutMs (up to 5 minutes). For very large jobs, split the work across multiple runs.
Need help setting up a schedule? Reach out to support@stardeck.ai.