Every few minutes, something on my server checks whether I’ve left a text message unreplied. Something else notices a relationship going cold and queues up a nudge for this afternoon. A third thing just pulled in a Google Meet transcript and is waiting for me to say “process it.”
None of these know about each other. They don’t need to.
I run a coworking space, a virtual mailbox service, an education business, and a consulting practice. Three inboxes, two calendars, a membership platform, noise sensors, a wifi network, supplier reorder cycles, and a pile of relationships I’m trying not to let go stale.
Things fall through the cracks. That’s the default state.
A birthday passes without a note. A supplier reorder window closes before I notice. An approval email sits for two days because I didn’t see it come in.
I built Andy, my AI executive assistant, to catch the things I’d otherwise miss. The conversational part gets the most attention, but the real backbone is the job scheduler - automated routines running in the background, each one there because without it, something specific was falling through the cracks.
The scheduling problem nobody warns you about
Early on, I hit a problem that wasn’t obvious until it was really obvious: multiple jobs all calling Gmail at the same time.
Rate limit errors. Jobs piling up behind each other. Expensive operations overlapping.
The system worked fine with a handful of jobs. Add more and it becomes a mess.
Most AI assistant setups I’ve seen use a heartbeat pattern - check every few seconds, see if there’s work, do it. Simple. Also terrible once you’re past a dozen routines competing for the same APIs.
I use Bree, a Node.js job scheduler, and the key word is deterministic. Every job has a specific schedule. Every job gets its own process. If one crashes, it doesn’t take down the others. And I can stagger them so they never compete for the same resources.
Staggering by hand, until you can’t
My session sync runs at :05, :20, :35, :50. Calendar sync at :03, :18, :33, :48. Memory extraction at :12, :27, :42, :57. They never collide. This matters when your system talks to Gmail, Google Calendar, Luma, Nexudus, Twitter, Discord, Front, and about a dozen other services.
Without careful scheduling, I’d be debugging rate limits instead of running my business.
Manual staggering works for a while. Eventually you start getting collisions you hadn’t planned for. I stole the fix from Claude Code. Their scheduler uses deterministic jitter - a small random-looking delay before each job runs, derived from the job’s name. Same job always gets the same offset, but jobs that share a schedule naturally spread out.
Every job now gets up to 10% of its period as jitter, capped at 30 seconds. A job that runs every 15 minutes might wait 8 seconds before starting. Another on the same schedule waits 22 seconds. They never collide, and I didn’t have to hand-tune every cron offset.
Queues for the jobs that can’t overlap
Some jobs can’t safely run in parallel at all, so those go through a pg-boss queue instead of running directly. The job creates a queue entry, a worker picks it up when it’s free. No collisions, no coordination needed.
The full list
Here’s every job, organized by what it does.
Email & Communication
poll-andy-email - Every minute
Handles incoming emails to andy@indyhall.org. Auto-replies to trusted senders and drafts responses for my approval on everything else.
poll-alex-email-patterns - Every minute
Watches my personal inbox for specific types of emails (order confirmations, notifications, etc.) and routes each one to the right handler automatically.
poll-front-mail - Every 5 minutes
Handles unassigned conversations in our shared Indy Hall inboxes. Filters out noise and processes the rest so nothing sits unanswered.
aihero-to-discord - Every minute
Forwards emails sent to our AI Hero consulting inbox into a Discord thread so I can track client communication without checking another inbox.
aihero-calendar-sync - Every 30 minutes
Keeps a Google Calendar in sync with a launch planning spreadsheet so the email send schedule is always visible on my calendar.
poll-google-meet-transcripts - Every 5 minutes
Catches Google Meet recordings as they come in, saves the transcript, and gives me a one-click button to process meeting notes.
Relationships & People
relationship-refresh - Daily at 8am
Scans my sent emails and updates my relationship files so I always know when I last talked to someone and what we discussed.
relationship-nudges-afternoon - Daily at 2pm
Flags relationships that are going stale and nudges me in Discord while I’m still in work mode. The ones closest to going cold show up first.
sync-birthday-db - Daily at 6am
Keeps my birthday list current with Indy Hall’s active members and any birthdays I’ve collected from other sources.
daily-birthday-email - Daily at 8am
Emails me today’s and tomorrow’s birthdays and Indy Hall member anniversaries so I never miss one.
daily-reflection-prompt - Weekdays at 4pm
Posts two fresh reflection questions to our team channel based on who checked in at Indy Hall today. Prompts my partner Adam to capture member stories while they’re fresh.
gather-member-highlights - Daily at 10am
Reads Adam’s daily reflection replies and extracts member stories and observations. These become raw material for our newsletter.
date-cadence-nudge - Sundays at 6pm
Tracks whether I’m keeping up with recurring personal commitments (date nights, vacations, etc.) against monthly or quarterly targets. Nudges me when I’m falling behind.
Calendar & Events
dispatch-sync-luma-events - Every 15 minutes
Keeps my event database and Google Calendar in sync with Luma so new events and RSVPs show up everywhere automatically.
dispatch-sync-gcal-events - Every 15 minutes
Gives Andy full calendar awareness so they can prep for meetings and flag scheduling conflicts.
Tasks & Projects
daily-task-digest - Daily at 8:05am
Emails me a summary of overdue, due-today, and upcoming tasks across all projects so I know what needs attention before I start working.
pm-agent-morning - Weekdays at 7:30am
Ranks my top 3 priorities for the day and posts them to Discord with action buttons. Runs before my morning briefing so priorities are already set.
pm-agent-afternoon - Weekdays at 2:30pm
Afternoon priority re-rank that catches things that shifted during the day. On Fridays, runs a weekly training cycle instead.
morning-overview - Weekdays at 8:30am
My daily briefing. Assembles calendar, inbox, priorities, and relationship status into a single Discord post so I can get oriented in one place.
regenerate-next-caches - Daily at 2am
Rebuilds the data behind my “what should I work on next” recommendation engine so suggestions are fresh each morning.
nightly-eod-prompt - Daily at 6pm
Generates an end-of-day review and posts a dashboard to Discord. I can reply in the thread to continue the conversation.
Messages & Social
sync-imessages - Every 15 minutes
Alerts me in Discord when I have unreplied text messages, filtering out spam and short codes. I don’t have to check my phone to know if someone’s waiting on a reply.
upload-imessage-attachments - Every 15 minutes
Makes iMessage photos and attachments available as URLs so Andy can reference them in conversations and notes.
process-twitter-bookmarks - Every 30 minutes
Takes tweets I’ve bookmarked, figures out what they’re about, and files them into my knowledge base. Bookmarking is the only thing I have to do - the rest happens on its own.
sync-twitter-archive - Twice daily at 9am and 9pm
Keeps a local archive of my tweets so I can search and reference them later.
social-media-snapshot - Daily at 9am
Grabs engagement numbers across Twitter, Instagram, TikTok, and LinkedIn for whatever I’m actively promoting. Shows me what’s working and what’s not.
sync-discrawl - Every 6 hours
Archives Discord messages across all my guilds so conversations are searchable even after they scroll off screen.
AI Wearable (Omi)
omi-poll-conversations - Daily at midnight and 5pm
Pulls in conversations captured by my Omi wearable. Runs twice - once at 5pm for the workday, once at midnight for the evening.
omi-morning-digest - Daily at 8:10am
Emails me a “Morning Field Notes” summary of yesterday’s conversations - ideas that came up, things I committed to, people I talked about, events mentioned. Also posts the most interesting unanswered question to a Discord channel where I can chew on it.
Knowledge & Memory
catch-memories - Every 15 minutes
Reads my recent work sessions and pulls out things Andy should remember - decisions I made, preferences I stated, things I corrected. Without this, every conversation starts from scratch.
extract-session-facets - Twice per hour
Tags each work session with what it was about, what patterns showed up, and what it cost. Lets me search and see where my time actually goes.
generate-insights-report - Weekly on Sunday at 6am
Writes a weekly report (and a monthly one) showing patterns in how I’m working - what I’m spending time on, what’s shifting, where the hours are actually going.
dispatch-sync-claude-sessions - Every 15 minutes
Keeps the memory and insights systems up to date with my latest work sessions. Everything else in this section depends on this one running.
audit-knowledge - Weekly on Sunday at 5am
Checks my knowledge base for broken links, missing metadata, duplicates, and stuff that’s gone stale. Fixes what it can and flags the rest.
qmd-refresh - Hourly
Re-indexes my knowledge base for semantic search so when I ask Andy a question, the answers reflect recent additions.
watchlist-digest - Daily at noon
Checks saved articles and resources against their original sources for updates. If something I’m tracking has changed, I’ll know.
Infrastructure & Monitoring
backup-database - Every 30 minutes
Backs up the database to cloud storage. Coordinates with other heavy jobs so backups don’t compete for resources.
pm2-service-watchdog - Every 5 minutes
Makes sure all 6 core services are running and healthy. Auto-restarts anything that’s crashed and flags zombie processes.
queue-health-monitor - Every 15 minutes
Watches for the specific failure patterns that caused a past outage: stuck connections, slow responses, failed jobs, and error spikes. Alerts me before small problems cascade.
detect-runaway-processes - Every 15 minutes
Catches processes that are eating too much CPU or memory. I get Kill/Investigate/Dismiss buttons in Discord before things go sideways.
mcp-watchdog - Every 2 minutes
Kills tool server processes that have gone into CPU spin loops. They auto-restart cleanly on next use.
udm-health-monitor - Every 5 minutes
Watches the Indy Hall wifi network for problems - access points, latency, too many clients on one band, channel congestion. Only pings me if something stays broken, not for one-off blips.
update-port-registry - Every minute
Keeps a live map of which services are running on which ports so Andy always knows how to reach them.
dispatch-cleanup-orphaned-runs - Hourly
Cleans up background tasks that got stuck mid-run so they don’t block everything behind them.
Maintenance & Hygiene
cleanup-claude-sessions - Daily at 3am
Removes old session transcripts from the active directory to keep disk usage in check.
archive-claude-sessions - Weekly on Sunday at 4am
Moves older session files to long-term storage so they’re still accessible without eating local disk space.
cleanup-discord-attachments - Daily at 4am
Removes temporary image files that were downloaded so Andy could see them. They’ve served their purpose.
cleanup-podman-images - Weekly on Sunday at 3:30am
Frees up disk space. Old container images pile up fast if you don’t clean them out.
queue-maintenance - Weekly on Sunday at 3am
Housekeeping. Clears out old job records so the system stays snappy.
git-hygiene - 4x daily (9am, 1pm, 5pm, 9pm)
Automatically commits and pushes accumulated file changes in logical groups. Stays out of the way during active work sessions.
commit-byline-data - Every 6 hours
Saves code attribution data so I can see who (or what) wrote each piece of code over time.
Content & Documentation
check-broken-links - Daily at 9am
Scans the repo for broken links and auto-fixes what it can. Flags anything that needs manual review.
check-documentation-health - Daily at 4am
Makes sure my docs aren’t missing metadata or broken in ways that cause problems downstream. Fixes what it can on its own.
update-timeline - Weekly on Monday at 2am
Reviews the past week’s work and writes it up as a narrative timeline, creating a running history of the project.
timeline-monthly-synthesis - Monthly (first Monday at 2:30am)
Reads the past 4 weeks of timeline entries and writes a thematic synthesis of what happened that month.
audit-quality-review - Weekly on Sunday at 8pm
Reads through my audit trail and flags entries that are vague, have placeholder text, or are too thin to be useful. Keeps me honest about documentation quality.
Indy Hall Operations
ipostal-compliance-report - Weekly on Friday at 9am
Checks our virtual mailbox compliance status and emails me a report. Flags the subject as “ACTION REQUIRED” if any mailboxes need authorization.
ipostal-subscriber-sync - Daily at 6am
Keeps our virtual mailbox subscriber list current with a daily snapshot.
ipostal-approval-monitor - Every 15 minutes
Catches new virtual mailbox subscriber approval requests and kicks off the approval workflow so new subscribers don’t wait.
minut-daily-check - Daily at 9am
Checks the noise sensors, temperature, humidity, and battery levels in the Indy Hall space. Pings me if something is off or a sensor dies.
supplies-weekly-email - Weekly on Friday at 8am
Emails me a supplies status report with reorder alerts, recent spend, and anything that needs attention before the weekend.
supplies-scan-orders - Weekdays at 9am
Picks up order confirmation emails from our vendors so spend tracking stays current without manual entry.
supplies-recalculate-rules - Weekly on Sunday at 6am
Looks at our actual ordering history and adjusts the reorder timing. The alerts get smarter the longer it runs.
Session & Tool Management
track-claude-usage - Hourly
Logs my AI token usage and costs so I can track spending trends over time.
extract-commands - Hourly
Picks up new slash commands I’ve created during work sessions and makes them available in autocomplete.
check-cli-updates - Daily at 8am
Checks my CLI tools for available updates and gives me Approve/Skip/Snooze buttons for each one.
send-reminder-notifications - Every minute
Fires off any reminders that are due, including resurfacing snoozed Discord threads when their timer expires.
linkedin-session-keepalive - Every 5 days at 3am
Keeps my LinkedIn automation session alive so data collection doesn’t silently break. Alerts me if it needs manual intervention.
What makes this work
Stagger everything. Don’t put jobs on round numbers. If three jobs run at :00, they’ll fight over the same resources. Offset by a few minutes and you eliminate an entire class of problems.
Every job should be safe to run twice. Crashes happen. Restarts happen. If a job can’t handle an unexpected re-run, it will cause problems, and you’ll be debugging at 2am. A non-idempotent job that crashes halfway through can silently send a duplicate email or corrupt a record - and you won’t know until someone complains.
Separate the scheduler from the work. The scheduler decides when things run. The actual work happens in isolated scripts. When something breaks, you know exactly where to look - and you can run the script manually to reproduce the failure without waiting for the next scheduled window.
Monitor your monitors. I have jobs that watch other jobs. The service watchdog checks that the scheduler itself is running. The health monitor checks that the queue workers are healthy. Without this, a single silent failure cascades into a really confusing morning. My relationship nudges stopped firing for three days once before I noticed - the scheduler had crashed, everything looked fine from the outside, and no one told me.
Start with one job and earn the next. Each one solved a problem I was actually having. The system grew because each new job made the rest more useful.
Every job on this list exists because without it, something I care about was falling through the cracks. It’s not a thing that runs while I sleep. It’s a thing that runs while I work.