Schedule App-Managed Jobs on Vercel
Deploy static and dynamic schedules that run jobs on Vercel.
Introduction
30 Second Summary
Reliable apps often need work to happen after nobody is watching. Some jobs follow a fixed routine. Others need to be scheduled as the app's needs change.
In this project, you will deploy a Next.js app with a fixed cleanup job using Vercel Schedules. The running app will also create a daily digest schedule for itself.
What You'll Build
Your deployed app shows a fixed cleanup schedule beside a daily digest schedule it created while running.
By the end of this project, you'll have:
- A deployed scheduler with an hourly cleanup job that stays private from browser requests.
- A runtime-created schedule that appears in the Schedules tab without another deployment.
- Dashboard controls for triggering or pausing jobs, plus function logs that prove each run happened.
- Secret Mission: An optional challenge to push your scheduling skills further.
Are there any prerequisites?
You'll need a Vercel account plus Node.js, Git, and the Vercel CLI. The first step walks you through the project setup.
Before We Start
Your scheduled app needs a reliable path from your computer to a live deployment. Missing account access or local tools would block that path before you write any code.
This step confirms that your Vercel account is ready. You will also reach the Vercel Dashboard.
You will then check your Node.js toolchain. A final check confirms that Git is available.
In this step, get ready to:
- Access your Vercel Dashboard.
- Confirm your Node.js toolchain is available.
- Prepare the remaining local development tools.
Access the Vercel Dashboard
Your Vercel account manages the app you deploy later. The dashboard is where you will inspect its schedules plus their runs.
Vercel handles sign-in details on its own website. Your credentials never go into this project.
Your path depends on whether you already have a Vercel account.
✔️ I already have a Vercel account
- Open the Vercel login page in your browser.
- Select the login method connected to your account.
You will move into the authentication flow for that login method.
- Complete the authentication prompts.
You should reach the Vercel Dashboard. You should also see your profile picture near the top-right corner.
ⓧ I need a Vercel account
- Open the Vercel sign-up page in your browser.
- Select Continue with Email.
You will see a field where you can enter your email address.
- Enter your email address.
Vercel sends a six-digit one-time password to that address.
- Find the one-time password in your inbox.
- Enter the one-time password on the Vercel sign-up page.
You should reach the Vercel Dashboard. You should also see your profile picture near the top-right corner.
Your Vercel access is ready. You now have the dashboard that will show each schedule created during the project.
Can't reach the dashboard?
Check that you selected the same login method used when the account was created. If you signed up with email, request a fresh one-time password from the login page.
Get help with accessing my Vercel account.
Verify Node.js and npm
Node.js runs the JavaScript tools used to create the app. npm provides the packages that the project needs.
Your route to the terminal depends on your operating system.
macOS
- Press Command-Space to open Spotlight.
- Type Terminal into the search field.
- Press Return to open Terminal.
You should see a Terminal window with a command prompt.
Windows
- Press the Windows key to open Windows Search.
- Type Windows PowerShell into the search field.
- Select Windows PowerShell from the results.
You should see a Windows PowerShell window with a command prompt.
- Check the Node.js toolchain by running these commands:
node --version
npm --version
What do these checks prove?
- The first command asks node to print the installed Node.js version.
- The second command asks npm to print its installed version.
- Two version lines confirm that both commands are available from your terminal.
Choose the tab that matches the terminal output you received.
✔️ I see two version numbers
Your terminal can access Node.js plus npm. This toolchain is ready for the project.
ⓧ A command is missing
A missing command means Node.js is unavailable to this terminal. Installing the LTS release also installs npm.
- Open the official Node.js download page.
- Select the LTS installer for your operating system.
Your browser should begin downloading the installer for your computer.
- Run the downloaded installer.
The installer should confirm when Node.js has been added to your computer.
- Close your current terminal window.
- Reopen Terminal or Windows PowerShell using the earlier search steps.
- Run the version check above again.
You should now see one version line for Node.js. A second version line should appear for npm.
That is the JavaScript toolchain confirmed. Your computer can now run the setup commands used in the next step.
Still missing Node.js or npm?
Make sure you reopened the terminal after installation. An older terminal window may still be using the previous command path.
Get help with finding Node.js or npm after installation.
Confirm Git and your code editor
Your code editor gives you a place to work with the project files. Git tracks those files as the project changes.
- Use your operating system's app search to find your installed code editor.
- Select the code editor from the search results.
You should see the editor open to its welcome screen or an empty window.
Can't find a code editor?
Install the code editor you plan to use from its official website. Reopen it through your operating system's app search after installation.
Get help with choosing a code editor for this project.
Before you run this final local check, do you expect Git to print a version number or report that the command is unavailable?
- Return to your terminal to check Git by running this command:
git --version
What does this check prove?
The git command asks Git to print its installed version. A version line confirms that the terminal can find Git.
Choose the tab that matches what your terminal displays.
✔️ I see a Git version
Git is installed. Your terminal can use it to track the project files you create next.
ⓧ Git is unavailable
Git needs to be installed before the project can track file changes.
- Open the official Git installation page.
- Choose your operating system.
You will see the installation path for your platform.
- Complete the Git installation.
The installer should confirm when Git has been added to your computer.
- Close your current terminal window.
- Reopen Terminal or Windows PowerShell using the earlier search steps.
- Run the Git version check above again.
You should now see a line containing the installed Git version.
Git still unavailable?
Reopen the terminal after the installation finishes. If Git remains unavailable, confirm that you used the installer for your operating system.
Get help with making Git available in my terminal.
Your workspace is ready. You can access Vercel from the browser while your terminal plus code editor handle the local project.
Your account plus local tools are in place. Next, you will create the Next.js project and deploy its first live version.
Create and Deploy the Next.js App
The schedules you build later need a real application to own their code. A local Next.js project gives every job a place to run.
In this step, you will create a Next.js app with the Vercel Schedules SDK installed. You will deploy that starter to Vercel so every later schedule has a live project behind it.
In this step, get ready to:
- Create a local Next.js project that runs in your browser.
- Install the @vercel/schedules package.
- Link the project to Vercel and open its live deployment.
Create and run the Next.js app
The project folder needs a predictable home on your computer. Your Desktop keeps it easy to find during this project.
- Move to your Desktop by running this command:
cd ~/Desktop
What does this command do?
The cd command changes the terminal location. The ~/Desktop path places the new project on your Desktop.
The Next.js scaffolder creates the starter files and installs the framework dependencies. The first run can take a few minutes while npm downloads everything.
- Create the my-app project by running this command:
npx create-next-app@latest my-app --yes
What does this command do?
- The create-next-app tool generates a working Next.js starter inside my-app.
- The --yes option accepts the current defaults without stopping for setup questions.
- The scaffold installs the dependencies needed to run the starter locally.
When the command finishes, your terminal confirms that the app was created inside the my-app folder.
Project creation stopped?
Check that your internet connection is active. Confirm that the terminal can run node and npm commands.
If a partial my-app folder remains after a failed attempt, remove that incomplete folder before trying the scaffold again.
Help me diagnose why create-next-app stopped before creating my project.
- Enter the new project folder by running this command:
cd my-app
Where is the terminal now?
The terminal now works from inside my-app. Every project command in the rest of this step runs from this folder.
A local development server proves the generated application can compile and serve a page. This gives you a visible result before you add any scheduling features.
- Start the local development server by running this command:
npm run dev
What does this command do?
The dev script compiles the Next.js starter. It keeps the server running so your browser can load the app.
- Open http://localhost:3000 in your browser.
You should see the default Next.js starter page. This confirms the generated app runs correctly on your computer.
Local page not loading?
Confirm that the development server is still running in your terminal. Use the local address printed by the server if it selected a different available port.
Help me debug why my generated Next.js starter does not load in the browser.
- Stop the local server by pressing Ctrl+C in the terminal.
You have your first visible win. The Next.js starter now runs on your machine.
Install the Schedules SDK
The starter app can serve pages now. The schedules package adds the APIs that later steps use to handle jobs and create schedules at runtime.
- Install the schedules package by running this command:
npm i @vercel/schedules
What does this command do?
- The npm installer downloads @vercel/schedules into the project.
- The installation records the package in package.json so Vercel installs it during each deployment.
- The package lock records the resolved dependency versions for repeatable installs.
- Confirm the package is installed by running this command:
npm ls @vercel/schedules
What should this show?
The dependency tree should include @vercel/schedules with its installed version. This proves the package is available to the local project.
Your terminal should list @vercel/schedules beneath the my-app project without reporting a missing dependency.
Package missing from the tree?
Confirm that your terminal is inside the my-app folder. The installation belongs in the same directory as package.json.
Help me fix an @vercel/schedules installation that does not appear in the npm dependency tree.
Link and deploy the project
A local app cannot receive schedule runs from Vercel. The Vercel CLI connects my-app to a hosted project before creating its production deployment.
Linking this project uses your Hobby account. This project path stays on the free plan.
The login command can open a browser confirmation flow. Completing that flow gives the CLI permission to create the project in your account.
- Prepare to confirm Vercel access in your browser if the CLI requests it.
- Authenticate the Vercel CLI by running this command:
vercel login
What does this command do?
This command authenticates the CLI with your Vercel account. The terminal resumes after the browser confirmation succeeds.
Your terminal should confirm that the CLI can use your account.
Login flow not completing?
Return to the browser window opened by the CLI. Confirm that you are using the same Vercel account that has the Hobby plan.
Help me complete the Vercel CLI authentication flow.
Project linking creates a Vercel project for the local folder. The command asks where the project belongs before it records the connection.
- Select your personal Hobby account when the CLI asks for a scope.
- Choose to create a new Vercel project from the current folder.
- Keep the detected Next.js project settings.
- Link the local folder by running this command:
vercel link
What does this command do?
The link command associates my-app with the new Vercel project. It stores the project connection inside the local .vercel directory.
Your terminal should confirm that the local directory is linked to a Vercel project under your Hobby account.
Project linked to the wrong account?
Stop the prompt if the expected Hobby account is missing. Confirm the browser and CLI use the same Vercel account before linking again.
Help me correct a Vercel project linked to the wrong scope.
The production deployment can take a few minutes while Vercel installs dependencies and builds the Next.js app. Ongoing build output means the deployment is still progressing.
Before you deploy, do you expect the terminal to finish with a local address or a public address?
- Deploy the linked project to production by running this command:
vercel deploy --prod
What does this command do?
The --prod option creates a production deployment. Vercel assigns the successful build to a public production URL.
When the build succeeds, the terminal prints a public deployment URL. This is the live version of your Next.js starter.
- Record the public URL here: your Vercel deployment URL.
- Paste your Vercel deployment URL into your browser address bar.
You should see the same Next.js starter page that ran locally. The address now uses a public Vercel domain.
- Return to the Vercel Dashboard from earlier.
- Select the my-app project from your projects list.
- Confirm the project belongs to your Hobby account.
- Confirm the latest production deployment uses the live URL you opened.
That is your app online. Your local Next.js project is now connected to a live Vercel deployment.
Production deployment failed?
Read the final build lines in the terminal for the file or dependency that stopped the deployment. Confirm that the local dependency check still lists @vercel/schedules.
Help me diagnose a failed production deployment of my Next.js schedules project.
✔️ Awesome, I've got everything!
Great. Your local dependency and live deployment are both ready for the scheduling work ahead.
ⓧ I'd like to double check the full code
No application code was changed by hand in this step. Double check that your generated project matches these exact states.
- Created locally as a Next.js application with @vercel/schedules installed in package.json.
- Created on the Vercel Hobby plan, linked to the local Next.js project, and deployed successfully with a live deployment URL.
Your application foundation is live. Next up, you will add the static schedule that deploys with the project.
Add the Static Cleanup Schedule
Your Next.js app is already live at its deployment URL. It still has no recurring work to perform.
Vercel Schedules reads static job definitions during deployment. In this step, you will connect an hourly schedule to a private cleanup function.
In this step, get ready to:
- Build a private cleanup handler with handleSchedule.
- Define the hourly schedule in vercel.json.
- Redeploy the app so the schedule appears in Vercel.
Create the private cleanup function
The handleSchedule wrapper validates each scheduled dispatch. It also gives your callback metadata about the run.
- Create api/cleanup.ts inside the top level of your local Next.js project by adding the code below:
import { handleSchedule } from '@vercel/schedules';
// Record the schedule name and planned run time in the function logs
export const POST = handleSchedule(async (metadata) => {
console.log(`Running ${metadata.name} at ${metadata.scheduledAt}`);
});
What does this code do?
- The POST export receives scheduled runs.
- The handleSchedule wrapper checks that each request is a valid schedule dispatch.
- The metadata.name value identifies the schedule that started the run.
- The metadata.scheduledAt value records when the run was due.
- Save api/cleanup.ts.
- Confirm that cleanup.ts appears inside api/ in your editor sidebar.
You should see no problem markers on the import or the POST export.
Seeing a problem in the cleanup function?
- Confirm that the file path is exactly api/cleanup.ts.
- Check that @vercel/schedules is still listed in package.json.
Ask for help with the handler error.
✔️ Awesome, I've got everything!
Good work. Your cleanup handler is ready to receive authenticated schedule dispatches.
ⓧ I'd like to double check the full code
import { handleSchedule } from '@vercel/schedules';
// Record the schedule name and planned run time in the function logs
export const POST = handleSchedule(async (metadata) => {
console.log(`Running ${metadata.name} at ${metadata.scheduledAt}`);
});
Define the hourly schedule
The project configuration connects a cron expression to the cleanup function. It also marks that function as a private schedule target.
- Create vercel.json inside the top level of your local Next.js project by adding the configuration below:
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"schedules": {
"cleanup-hourly": {
"schedule": "0 * * * *",
"function": "api/cleanup.ts"
}
},
"functions": {
"api/cleanup.ts": {
"experimentalTriggers": [
{ "type": "schedule/v1beta" }
]
}
}
}
How does this configuration work?
- The schedules object names the job cleanup-hourly.
- The 0 * * * * expression schedules a run at the start of every hour.
- The function value targets api/cleanup.ts.
- The schedule/v1beta trigger makes the cleanup function private.
The trigger is currently a beta feature. Its configuration syntax may change as Vercel Schedules develops.
- Save vercel.json.
- Confirm that your editor recognizes the file as valid JSON.
You should see matching braces with no syntax problem markers in vercel.json.
Seeing a configuration problem?
- Confirm that the file is named exactly vercel.json.
- Compare every quote and comma with the full configuration below.
- Check that api/cleanup.ts matches the cleanup function path you created.
Ask for help checking the schedule configuration.
✔️ Awesome, I've got everything!
Your static schedule configuration now connects the hourly cadence to the private cleanup function.
ⓧ I'd like to double check the full code
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"schedules": {
"cleanup-hourly": {
"schedule": "0 * * * *",
"function": "api/cleanup.ts"
}
},
"functions": {
"api/cleanup.ts": {
"experimentalTriggers": [
{ "type": "schedule/v1beta" }
]
}
}
}
Redeploy and verify the schedule
Static schedules synchronize when you deploy. The updated deployment creates cleanup-hourly from your saved configuration.
This redeployment can take a little while to finish. A quiet terminal during the build does not mean it has stalled.
- Redeploy the linked project to production by running this command:
vercel deploy --prod
What does this command do?
The Vercel CLI deploys the current local project to production. Vercel reads vercel.json during that deployment.
The deployment also applies the private trigger to api/cleanup.ts.
When the deployment finishes, you should see a successful deployment result with its URL.
Deployment did not finish?
- Confirm that your terminal is inside the linked local Next.js project.
- Check the deployment output for the first file or configuration problem.
- Correct any reported path mismatch before redeploying.
Ask for help with the deployment output.
Before you check the dashboard, do you expect the hourly job to be present after that deployment?
- Return to the Vercel Dashboard from earlier.
- Select the project you just deployed.
- Click the Schedules tab.
You should see cleanup-hourly listed as enabled. Its expression should be 0 * * * *.
That is the static half of your scheduling system working. Your deployment now owns an hourly private job.
Schedule missing from the tab?
- Confirm that vercel.json sits at the top level of the linked local project.
- Check that the successful deployment came from that linked project.
- Verify that the schedule name in vercel.json is exactly cleanup-hourly.
Ask for help tracing the missing schedule.
Your app now owns an enabled hourly schedule. Next, you will run it on demand to inspect its function logs.
Run and Inspect the Cleanup Schedule
Your hourly cleanup job is registered with Vercel Schedules. Its configuration has reached production.
In this step, you will trigger cleanup-hourly from the dashboard. You will inspect the resulting logs to trace the invocation.
In this step, get ready to:
- Trigger the cleanup schedule on demand.
- Confirm the manual run appears in its execution history.
- Inspect the invocation details in the function logs.
Run the schedule on demand
An on-demand run lets you test the deployed cleanup function immediately. It uses the schedule that is already registered in your project.
- Return to the project's Schedules tab from earlier.
- Select cleanup-hourly to open its details.
Before you trigger it, do you think an on-demand run will alter the hourly cadence or leave it in place?
- Click Run Schedule.
- Review the schedule's execution history after the run completes.
You will see a new run with its outcome and duration. The next hourly run remains scheduled.
What Did the Manual Run Prove?
Run Schedule invokes the existing target immediately without changing its cadence. This gives you a production test without waiting for the next hour.
You now have a real invocation in the execution history. The hourly schedule remains active for future runs.
Inspect the function logs
Runtime logs capture the output generated by each function invocation. They connect the schedule run to the metadata received by the cleanup function.
Before you inspect the newest invocation, which schedule details do you expect the function to have recorded?
- Select Logs in the project sidebar.
- Enter cleanup-hourly in the main search field.
- Select the most recent Vercel Function Invocation.
- Scroll to Log Messages in the invocation details.
You will see a log message containing cleanup-hourly and its scheduledAt time. These details confirm which schedule ran and when Vercel scheduled the invocation.
Why These Log Values Matter
- The cleanup-hourly name confirms that the expected schedule invoked the function.
- The scheduledAt value records the scheduled time for this execution.
- Together, these values give you a trace from the dashboard run to the function output.
Can't Find the New Log?
- Refresh the Logs view to load the latest invocation.
- Remove the search text to confirm that the function invocation is present.
- Return to the schedule's execution history to confirm that the manual run completed.
Help me trace a manually triggered Vercel schedule into its function logs.
That's the full trace captured: the manual run is tied to cleanup-hourly through its scheduledAt value.
Your schedule now runs on demand and leaves a trace in the function logs. Next, you will verify that the cleanup function stays private.
Verify the Cleanup Function Is Private
Your hourly cleanup ran on demand. Its logs included cleanup-hourly with the scheduledAt time.
Scheduled jobs can hold sensitive maintenance logic. A public browser route would expose the wrong entry point.
This step tests the deployed path to prove that Vercel Schedules alone can invoke the private function.
In this step, get ready to:
- Locate the function target used by cleanup-hourly.
- Try to reach the target through your live deployment URL.
- Confirm that the cleanup function has no public browser route.
Locate the cleanup function target
The function value in vercel.json identifies the target registered with the schedule. You can reuse that identifier to test the equivalent path against your deployment.
- Open the existing vercel.json file in your local project with your code editor.
- Find the cleanup-hourly entry under schedules.
- Locate the function value inside that entry.
- Record the value here: your cleanup function target.
Test the path in your browser
The browser sends a normal public request. The deployment should resolve this path as missing before the cleanup code runs.
- In your browser, return to the project's live deployment URL from earlier.
- Select the browser's address bar.
- Set the path after the deployment domain to / followed by your cleanup function target.
Before you load the path, do you think the browser can reach the function that the scheduler invoked?
- Press Enter to load the path.
You should see a missing page or route response from the deployment. You should not see the cleanup function's log output in the browser.
What Proves the Function Is Private?
The schedule/v1beta trigger removes the function's public URL. Vercel's scheduler reaches the function through private infrastructure.
Your earlier cleanup-hourly run proves that the private target still works for its intended caller.
Seeing Cleanup Output?
If the browser shows cleanup output, confirm that you used the function value from the cleanup-hourly entry. A similarly named public route can lead to the wrong test.
Help me work out why my scheduled cleanup function is reachable from the browser.
That is the security boundary doing its job. Your cleanup function remains available to its schedule without exposing a browser route.
Your cleanup work now stays off the public web. Next, you'll let the app create another schedule while it runs.
Create a Daily Digest Schedule
Your private cleanup function now runs every hour on Vercel Schedules. Its cadence lives in vercel.json.
The daily digest needs to appear while the app is already running. A dynamic schedule lets the deployed app register this job immediately.
In this step, get ready to:
- Build a public API route that creates the daily digest schedule.
- Deploy the new route to the existing Vercel project.
- Call the route to register the schedule at runtime.
Build the schedule creation route
A Next.js Route Handler gives your deployed app a public endpoint. When called, this endpoint creates a schedule that publishes its payload to a Queue topic.
Why create it at runtime?
Static schedules live in vercel.json. They change when you deploy.
Dynamic schedules fit jobs chosen while the app is running. Schedules.create() registers the new job immediately.
- Create app/api/schedules/route.ts in the local project with your editor's file creation control.
- Paste the schedule creation route into app/api/schedules/route.ts:
import { Schedules } from '@vercel/schedules';
export async function POST() {
// Register the digest job while this deployment is running
const schedule = await Schedules.create({
name: 'daily-digest',
target: { topic: 'daily-digest' },
expression: { type: 'cron', cron: '0 9 * * *' },
timezone: 'UTC',
payload: { reportType: 'summary' },
});
// Return the schedule so the caller can confirm its configuration
return Response.json(schedule);
}
What does this route do?
- The POST function exposes the handler at /api/schedules.
- The Schedules.create() call registers daily-digest as a dynamic schedule.
- The 0 9 * * * expression matches every day at 09:00 UTC.
- The daily-digest topic receives a payload containing reportType when the schedule runs.
- The JSON response exposes the new schedule's ID and state.
- Save app/api/schedules/route.ts.
- Confirm your editor shows the saved file under app/api/schedules.
Route file showing an import error?
Confirm the import uses @vercel/schedules exactly. The package already exists in this project.
Check that route.ts sits inside app/api/schedules.
Help me debug the schedule creation route.
✔️ Awesome, I've got everything!
Great. Confirm that app/api/schedules/route.ts is saved before you deploy it.
ⓧ I'd like to double check the full code
import { Schedules } from '@vercel/schedules';
export async function POST() {
// Register the digest job while this deployment is running
const schedule = await Schedules.create({
name: 'daily-digest',
target: { topic: 'daily-digest' },
expression: { type: 'cron', cron: '0 9 * * *' },
timezone: 'UTC',
payload: { reportType: 'summary' },
});
// Return the schedule so the caller can confirm its configuration
return Response.json(schedule);
}
This complete file should match your saved route before deployment.
Deploy the schedule route
The SDK authenticates through the deployment's OIDC token. Running the route on Vercel gives Schedules.create() the project context it needs.
The deployment can take a few minutes while Vercel builds the updated app. Continued build output means the process is still moving.
- Deploy the saved project to production by running:
vercel deploy --prod
What does this command do?
The command sends the latest local files to the linked Vercel project. The production deployment now includes the public /api/schedules route.
- Wait for the terminal to confirm that the production deployment is ready.
- Record the production URL shown in the deployment output: your Vercel production URL.
Your deployed app can now create schedules from its own server-side code. The existing cleanup-hourly schedule remains unchanged.
Deployment not completing?
Check the build output for a file path pointing to app/api/schedules/route.ts. Compare that file with the full-code tab above.
Confirm the terminal is running inside the linked local Next.js project.
Help me diagnose the failed Vercel deployment.
Create and verify the dynamic schedule
Calling the deployed route runs Schedules.create() inside the production environment. The new schedule takes effect immediately.
Before you call the route, do you expect it to replace cleanup-hourly or create a separate schedule?
- Create the daily digest schedule by sending a POST request to the deployed route:
curl -X POST [[PRODUCTION_URL="your Vercel production URL"]]/api/schedules
What does this request do?
The curl command sends a POST request to your public Route Handler. The handler returns the schedule object as JSON.
Look for daily-digest in the response. Its state should be active.
That is the key result. Your running app has created an active schedule without changing vercel.json.
Request not returning the new schedule?
A response mentioning schedule_already_exists means this route already created daily-digest.
A response mentioning forbidden means the current Vercel role cannot create a schedule in this environment.
Help me debug the dynamic schedule request.
Before you refresh the dashboard, which two schedule names do you expect to see together?
- Return to the project's Schedules tab from earlier.
- Refresh the browser page.
- Select the daily-digest schedule.
You should see cleanup-hourly and daily-digest listed together. The new schedule should be enabled with the 0 9 * * * expression.
Its target should show the daily-digest Queue topic. The configured payload should contain reportType set to summary.
The schedule appeared after the route call. You did not need another deployment after creating it.
Your app now owns a schedule that code created at runtime. Next up, you will pause that dynamic schedule and bring it back without redeploying.
Pause and Resume the Daily Digest
Your app can already create daily-digest while it is running. Now you need an operational switch that controls when the digest runs.
Vercel Schedules lets you pause or resume one schedule without redeploying the project. You will test both states in the dashboard so the digest finishes enabled.
In this step, get ready to:
- Locate the runtime-created daily-digest schedule.
- Confirm daily-digest enters a paused state.
- Confirm daily-digest returns to an enabled state.
Pause the daily digest
Pausing a dynamic schedule stops its recurring runs while preserving the schedule for later. This gives you temporary control without deleting its configuration.
Before you change the schedule, what status do you expect to see after disabling it?
- Switch back to the Vercel Dashboard project from earlier.
- Select the Schedules tab.
- Select daily-digest from the schedule list.
- Use the schedule state control in the daily-digest details to disable it.
- Check the status shown for daily-digest.
You will see daily-digest in a paused state. The schedule remains listed in the dashboard.
You have just paused one automated job without disturbing the enabled cleanup-hourly schedule.
Status Not Changing?
- Refresh the Schedules tab to load the latest state.
- Confirm that you selected daily-digest instead of cleanup-hourly.
Help me work out why my Vercel schedule is not showing its paused state.
Resume the daily digest
Enabling the schedule returns it to its recurring cadence. This proves you can restart app-created work directly from the dashboard.
Before you resume it, what status do you expect to see once the change is accepted?
- Use the schedule state control to enable daily-digest.
- Check the updated status shown for daily-digest.
You will see daily-digest with an enabled status. Its recurring schedule is active again.
That completes the control loop. Your app-created digest can now be paused or resumed without a code change or redeploy.
Still Showing as Paused?
- Refresh the Schedules tab to retrieve the current status.
- Return to the daily-digest details to confirm that you enabled the correct schedule.
Help me diagnose why my Vercel schedule remains paused after I enabled it.
Secret mission
Run a Schedule Readiness Review
Create an operations readiness check for both schedules. Prove the private job ran. Audit the runtime-created job's live configuration.
Clean Up Your Resources
Clean Up Your Resources
Your app uses the Hobby plan for Vercel Schedules. Schedule usage stays at $0 while you remain within 500 schedule creations and 5,000 runs each month.
Decide whether to keep your app available, pause its schedules, or delete the resources from this project.
Resources you used:
- The Vercel project with its live deployment.
- The static cleanup-hourly schedule defined in vercel.json.
- The dynamic daily-digest schedule created while the app was running.
- The local Next.js project directory containing vercel.json.
Keep everything running
No action needed. Choose this if you want the live app and both schedules to remain available.
- The cleanup-hourly schedule continues running every hour.
- The daily-digest schedule remains enabled with its configured payload.
- The live deployment stays available through your existing Vercel project.
- Monitor your monthly schedule usage to keep it within the Hobby plan allowance.
Pause - I'll come back to this later
Disable both schedules to stop new scheduled runs. Your deployment and local source code remain available for your return.
- Return to the Vercel Dashboard project from earlier.
- Select the Schedules tab.
- Find cleanup-hourly in the schedule list.
- Use the Disable control for cleanup-hourly.
- Find daily-digest in the schedule list.
- Use the Disable control for daily-digest.
You should see both schedules displayed with a paused status. Your project remains deployed.
- Enable cleanup-hourly from the same tab when you resume the project.
- Enable daily-digest from the same tab when you want its daily runs to resume.
Delete - I don't want to use this again
Deleting these resources is permanent. Keep the local directory until you are certain that you no longer need this scheduling pattern.
- Return to the Vercel Dashboard project from earlier.
- Select the Schedules tab.
- Find daily-digest in the schedule list.
- Open the action menu for daily-digest.
- Select the Delete option.
- Confirm the schedule deletion when prompted.
You should no longer see daily-digest in the Schedules tab.
- Select Settings for the same Vercel project.
- Select Advanced.
- Scroll to the project deletion area.
- Use the permanent project deletion control.
- Enter the project name when the confirmation prompt requests it.
- Confirm the project deletion.
The live deployment and the static cleanup-hourly schedule are removed with the project. You should no longer see the project in your Vercel Dashboard.
Your local source code remains on your computer. Use the matching platform tab to remove the directory that contains vercel.json.
macOS
- Press Cmd+Space to open Spotlight.
- Type Finder and press Enter to open it.
- Return to the location where you created the local Next.js project earlier.
- Select the directory that contains vercel.json.
- Move the selected directory to the Trash.
- Empty the Trash to remove the directory permanently.
- Return to the original location.
- Confirm that the project directory is no longer listed.
Windows
- Press the Windows key to open search.
- Type File Explorer and press Enter to open it.
- Return to the location where you created the local Next.js project earlier.
- Select the directory that contains vercel.json.
- Move the selected directory to the Recycle Bin.
- Empty the Recycle Bin to remove the directory permanently.
- Return to the original location.
- Confirm that the project directory is no longer listed.
Nice Work!
Nice Work!
You did it! Your deployed Next.js app now controls its own jobs through Vercel Schedules.
You've learned how to:
- Define an hourly cleanup job in vercel.json. Connect it to a private scheduled function.
- Use runtime schedule creation to add daily-digest without redeploying the app. Target its payload to a Queue topic.
- Use schedule controls to run or pause jobs from the dashboard. Confirm a manual run through function logs that show cleanup-hourly with its scheduledAt time.
- Complete an optional Secret Mission to push your scheduling skills further.
Ready to quiz yourself?