Repository navigation
[Chore] Move keeper scheduling off Vercel Cron #513
Description
Summary
vercel.json's crons array currently schedules both /api/v1/keepers/accrue (every 15 minutes) and /api/v1/keepers/rebalance (hourly, added in #469's PR). Neither can actually run: Vercel's Hobby plan restricts Cron Jobs to once per day, and both schedules are more frequent than that. Vercel's own deployment check fails with:
Hobby accounts are limited to daily cron jobs. This cron expression (*/15 * * * *) would run more than once per day. Upgrade to the Pro plan to unlock all Cron Jobs features on Vercel.
Motivation
This means the accrual keeper has not actually been running on any schedule since it was merged in #484: nothing is triggering it in production today, so Blend-backed vault TVL/APY has likely been stale since then, contradicting apps/docs/operations/accrual-keeper.md's documented 15-minute staleness guarantee. This is a live, silent gap, not just a blocker for the new rebalance keeper.
Proposed Solution
Discussed three options; moving scheduling off Vercel Cron entirely was chosen over upgrading to Pro or downgrading both keepers to a daily cadence (which would materially weaken the accrual keeper's existing staleness guarantee):
- Remove both entries from
vercel.json'scronsarray - Add a GitHub Actions workflow (e.g.
.github/workflows/keepers.yml) with twoschedule:triggers (*/15 * * * *for accrue,0 * * * *for rebalance) thatcurlthe respective endpoints withAuthorization: Bearer ${{ secrets.CRON_SECRET }} - Add
CRON_SECRETas a GitHub Actions repository secret (same value already used for Vercel's ownCRON_SECRET)
Confirmed this doesn't violate GitHub's usage policies: the schedule trigger calling an external endpoint on a timer is a standard, documented use case, well outside GitHub's actual abuse categories. Two operational caveats to design around, not blockers:
- GitHub auto-disables scheduled workflows after 60 days of repository inactivity (no pushes) — needs the repo to stay active or someone to notice and re-enable it
- Scheduled workflow timing is best-effort, not exact-to-the-minute under platform load, acceptable for a 15-minute/hourly keeper interval
Scope
| Field | Value |
|---|---|
| Area | API |
| Protocol affected | None |
| Network | testnet |
| Breaking change? | No (changes trigger mechanism only, not endpoint behavior) |
Alternatives Considered
- Upgrade to Vercel Pro: removes the restriction with no code changes, but is a billing decision, not something to default into silently.
- Downgrade both keepers to daily cron: stays on Hobby with native Vercel Cron, but weakens the accrual keeper's already-documented 15-minute staleness guarantee to a daily one, a real behavior regression for existing functionality.
Acceptance Criteria
-
vercel.json'scronsarray no longer schedules either keeper endpoint - A GitHub Actions workflow triggers both endpoints on their intended cadence via
CRON_SECRET -
apps/docs/operations/accrual-keeper.mdandapps/docs/operations/migration-keeper.mdupdated to describe the actual trigger mechanism - Verified the accrual keeper is actually running again in production (not just deployed) after this change
Activity
Chigybillionz commentedon Aug 14, 2026
Hello,
I’d like to work on this issue.
GitHub: https://github.com/chigybillionz
I understand the core problem: the current Vercel Cron configuration cannot execute the 15-minute accrual or hourly rebalance schedules on the Hobby plan, leaving the accrual keeper inactive in production.
I’ll move both schedules to GitHub Actions, remove the Vercel cron entries, securely invoke the keeper endpoints using
CRON_SECRET, and update the operational documentation to reflect the new trigger mechanism. I’ll also verify that the accrual keeper is actually executing after deployment rather than only confirming that the workflow is configured. 💻I’ll keep the existing 15-minute accrual guarantee and hourly rebalance cadence intact while avoiding a Vercel Pro dependency. 🚀
collinsezedike commentedon Aug 15, 2026
Go for it @Chigybillionz
grantfox-oss commentedon Aug 15, 2026
🦊 GrantFox — @Chigybillionz has been assigned to this issue!
Next steps:
Closes #513)Good luck! Track your progress on GrantFox.
collinsezedike commentedon Aug 21, 2026
Unassigning after no response to the 24-hour follow-up on #516. This is an active production outage, so reopening for anyone else to pick up.
Chigybillionz commentedon Aug 21, 2026
collinsezedike commentedon Aug 21, 2026
@Chigybillionz thank you for the update. I appreciate the honesty. This issue is open for anyone right now since it's an active production outage, so I can't hold it exclusively. If you want to pick it back up, you can reopen #516 and push new commits to that same branch or start a fresh PR. Comment under this issue when it's ready so I get notified and reassign the issue to you before reviewing. You have 24 hours from now, if it's not done by then I'll take it on myself.