apscheduler

Advanced Python scheduler — runs jobs at specified times using cron expressions, fixed intervals, or one-time dates. APScheduler 3.x features: BackgroundScheduler (runs in background thread), BlockingScheduler (blocks main thread), AsyncIOScheduler (asyncio-based), cron trigger (CronTrigger), interval trigger (IntervalTrigger), date trigger (DateTrigger), job stores (in-memory, SQLAlchemy, MongoDB, Redis), executors (ThreadPoolExecutor, ProcessPoolExecutor, AsyncIOExecutor), job persistence across restarts, misfire handling, coalescing, max_instances, add_job()/remove_job()/get_jobs(), job events and listeners.

Evaluated Mar 06, 2026 (0d ago) v3.x
Homepage ↗ Repo ↗ Developer Tools python apscheduler scheduler cron jobs interval periodic background
⚙ Agent Friendliness
67
/ 100
Can an agent use this?
🔒 Security
89
/ 100
Is it safe for agents?
⚡ Reliability
80
/ 100
Does it work consistently?

Score Breakdown

⚙ Agent Friendliness

MCP Quality
--
Documentation
85
Error Messages
80
Auth Simplicity
99
Rate Limits
99

🔒 Security

TLS Enforcement
90
Auth Strength
90
Scope Granularity
88
Dep. Hygiene
88
Secret Handling
88

In-process scheduler. Jobs run with process privileges — validate job function inputs. Persistent job store (SQL/Redis) for job definitions — secure access. Dynamic job scheduling from user input: validate job parameters to prevent resource abuse. Log job exceptions for security anomaly detection.

⚡ Reliability

Uptime/SLA
82
Version Stability
80
Breaking Changes
75
Error Recovery
82
AF Security Reliability

Best When

In-process background scheduling for Python applications needing cron, interval, and one-time tasks without external infrastructure — APScheduler is the most complete in-process Python scheduler.

Avoid When

Distributed scheduling (use Celery Beat), high-frequency sub-second tasks (use asyncio), or when external cron (system crontab) is simpler.

Use Cases

  • Agent periodic task — from apscheduler.schedulers.background import BackgroundScheduler; scheduler = BackgroundScheduler(); scheduler.add_job(cleanup_expired, 'interval', hours=6); scheduler.add_job(generate_report, 'cron', hour=8, minute=0); scheduler.start() — background; agent runs cleanup every 6 hours and report at 8am; runs in background thread
  • Agent cron scheduling — from apscheduler.triggers.cron import CronTrigger; scheduler.add_job(send_digest, CronTrigger(day_of_week='mon-fri', hour=9, minute=0, timezone='US/Eastern')); scheduler.start() — cron; agent schedules task with cron expression and timezone; day_of_week, hour, minute, second, month, day parameters
  • Agent async scheduling — from apscheduler.schedulers.asyncio import AsyncIOScheduler; scheduler = AsyncIOScheduler(); @scheduler.scheduled_job('interval', seconds=30); async def async_task(): await fetch_and_process(); asyncio.get_event_loop().run_until_complete(main()) — async; agent schedules coroutines in asyncio event loop
  • Agent persistent jobs — from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore; jobstores = {'default': SQLAlchemyJobStore(url='sqlite:///jobs.db')}; scheduler = BackgroundScheduler(jobstores=jobstores); scheduler.add_job(fn, 'interval', minutes=30, id='my_job', replace_existing=True) — persistent; agent survives restarts with SQLite job store
  • Agent dynamic scheduling — job = scheduler.add_job(process_item, 'date', run_date=datetime.now() + timedelta(hours=1), args=[item_id]); scheduler.remove_job(job.id) if cancelled; scheduler.reschedule_job(job.id, trigger='interval', hours=2) — dynamic; agent schedules one-time or dynamic jobs programmatically

Not For

  • Distributed job scheduling — APScheduler is per-process; for distributed use Celery Beat or Airflow
  • High-frequency scheduling (sub-second) — APScheduler has overhead; for microsecond-level use asyncio.sleep loops
  • APScheduler 4.x breaking changes — APScheduler 4.x (beta) has completely new API; this evaluation covers stable 3.x

Interface

REST API
No
GraphQL
No
gRPC
No
MCP Server
No
SDK
Yes
Webhooks
No

Authentication

Methods: none
OAuth: No Scopes: No

No auth — in-process scheduler library.

Pricing

Model: open_source
Free tier: Yes
Requires CC: No

APScheduler is MIT licensed. Free for all use.

Agent Metadata

Pagination
none
Idempotent
Partial
Retry Guidance
Not documented

Known Gotchas

  • Scheduler must be started and shutdown — scheduler.start() launches background thread; scheduler.shutdown() cleans up; missing shutdown: daemon thread may prevent clean exit; agent code: use try/finally or atexit: import atexit; atexit.register(lambda: scheduler.shutdown()); or use as context manager (APScheduler 4.x only)
  • Job exceptions don't crash scheduler — if job function raises, APScheduler logs the exception but continues running; agent code: add event listener to detect failures: scheduler.add_listener(job_error_handler, EVENT_JOB_ERROR); job_error_handler receives JobExecutionEvent with exception; use for alerting or retry logic
  • max_instances prevents concurrent runs — add_job(fn, 'interval', minutes=5, max_instances=1) prevents overlap if job takes >5 min; default max_instances=1; increasing allows concurrent runs; agent code: set max_instances=1 for jobs that should not overlap; coalesce=True collapses missed runs into one
  • Timezone handling critical for cron — scheduler = BackgroundScheduler(timezone='US/Eastern') or per-job; without timezone: uses local machine timezone; CronTrigger without timezone: ambiguous on DST transitions; agent code: always specify timezone explicitly for cron jobs: CronTrigger(hour=9, timezone='UTC'); use UTC for predictability
  • In-memory job store loses jobs on restart — default MemoryJobStore loses all jobs if process restarts; agent code needing persistence: use SQLAlchemyJobStore('sqlite:///jobs.db') or RedisJobStore; replace_existing=True with explicit job IDs for idempotent job registration at startup
  • BackgroundScheduler vs AsyncIOScheduler — BackgroundScheduler: thread-based, works anywhere, can run sync functions; AsyncIOScheduler: coroutine-based, must be in asyncio event loop, for async functions; agent FastAPI: use AsyncIOScheduler and start in lifespan startup; agent scripts: use BackgroundScheduler; mixing async jobs in BackgroundScheduler requires AsyncIOExecutor

Alternatives

Full Evaluation Report

Detailed scoring breakdown, competitive positioning, security analysis, and improvement recommendations for apscheduler.

$99

Scores are editorial opinions as of 2026-03-06.

5208
Packages Evaluated
26151
Need Evaluation
173
Need Re-evaluation
Community Powered