APScheduler
Python task scheduler with cron, interval, and one-off triggers, backed by pluggable persistent datastores for distributed job scheduling.
Repository Health
Technical Analysis
APScheduler (Advanced Python Scheduler) is a task scheduling and job queue library for Python that works equally well as an in-process cron replacement or as the backbone of a distributed job-processing system. A single scheduler instance can run standalone in a script, or multiple schedulers and workers can share a persistent data store to coordinate jobs across processes and nodes, giving small deployments and larger ones the same programming model.
The library ships both synchronous and asynchronous scheduler implementations, so it fits naturally into thread-based applications as well as asyncio or Trio-based ones, with documented integration paths for WSGI and ASGI web frameworks. Jobs and schedules can be persisted to PostgreSQL, MySQL, SQLite, or MongoDB, and event brokers (PostgreSQL, Redis, or MQTT) let multiple scheduler and worker processes stay in sync when a shared data store is used for horizontal scaling.
Scheduling logic is expressed through trigger classes — cron-style, fixed interval, calendar interval, and one-off date triggers — which can be combined with the library’s combining triggers, or replaced entirely with a custom trigger implementing the same interface. Additional controls include per-task concurrency limits, misfire grace periods, and randomized jitter, covering the operational needs of both simple background tasks and higher-volume job queues.
What You Get
- Synchronous and AnyIO-based asynchronous scheduler classes, so the same library works in thread-based apps and asyncio/Trio apps alike
- Four built-in trigger types — cron, interval, calendar interval, and one-off date — plus combining triggers and a documented interface for writing custom ones
- Pluggable persistent data stores (PostgreSQL, MySQL, SQLite, MongoDB) so schedules and jobs survive process restarts and can be shared across nodes
- Event brokers (PostgreSQL, Redis, MQTT) for coordinating multiple scheduler/worker instances against a shared data store
- Job executors for thread pools, process pools, async tasks, and Qt event loops, selectable per task
- Operational controls including max concurrent jobs per task, misfire grace time, and jitter to avoid thundering-herd job runs
Common Use Cases
- Running periodic maintenance jobs (cleanup, cache warming, report generation) inside a long-running Python service without an external cron daemon
- Building a lightweight, database-backed job queue for a web app using ASGI/WSGI, where jobs need to survive a process restart
- Coordinating scheduled work across multiple worker processes or nodes via a shared PostgreSQL, MySQL, or MongoDB data store
- Replacing ad hoc
time.sleeppolling loops with cron-style or calendar-interval triggers for recurring business logic - Scheduling one-off, delayed tasks (e.g. send this email in 10 minutes) alongside recurring ones in the same scheduler
Under The Hood
Architecture
APScheduler centers on two scheduler classes — AsyncScheduler (src/apscheduler/_schedulers/async_.py) built on AnyIO task groups, and a synchronous Scheduler (src/apscheduler/_schedulers/sync.py) that wraps the async one — both composed from a DataStore and an EventBroker supplied through dependency injection rather than hardcoded (src/apscheduler/abc.py defines these as abstract base classes alongside Trigger and JobExecutor). The default wiring uses MemoryDataStore and LocalEventBroker for single-process use, while datastores/sqlalchemy.py and datastores/mongodb.py swap in persistent, shareable backends without changing scheduler code. Jobs flow from Schedule objects (evaluated via Trigger.next()) into Job records acquired from the data store, dispatched to a JobExecutor (thread pool, process pool, async, or Qt), and their results recorded as JobResult events published through the event broker — a clean separation that lets a schedule live independently of the process that eventually executes it. Swapping the core DataStore abstraction would ripple through job/schedule persistence and event replay logic, but the trigger and executor layers are designed to be extended without touching the scheduler internals.
Tech Stack
The library targets Python 3.10+ and is built on anyio ~= 4.0 for its async/sync duality, attrs >= 22.1 for its declarative, validated data classes (schedulers, triggers, and structures are all @attrs.define), and tenacity for retry logic around data store operations (_retry.py). Persistence backends are optional extras: sqlalchemy[asyncio] >= 2.0.24 for the SQL data store, pymongo for MongoDB, asyncpg/psycopg for PostgreSQL-specific event brokering, and redis/paho-mqtt for the Redis and MQTT event brokers. Packaging uses setuptools with setuptools_scm for version derivation from git tags, and the project ships example integrations for FastAPI, Starlette, Flask, and a plain ASGI/WSGI app under examples/web.
Code Quality
Testing is built on pytest with pytest-mock and time-machine for clock control, organized into per-concern suites (test_schedulers.py, test_datastores.py, test_eventbrokers.py, test_serializers.py, plus a dedicated tests/triggers/ directory), and coverage is tracked via coverage.py scoped to the apscheduler package. Code style and static checks are enforced through a pre-commit configuration running ruff (lint and format), mypy (as a manual/opt-in stage with pinned stub dependencies), and codespell, backed by a GitHub Actions test.yml workflow. The codebase makes consistent use of attrs validators and converters for runtime type/value enforcement and leans on from __future__ import annotations plus explicit type hints throughout, giving it a typed, lint-enforced foundation even though mypy itself only runs on demand rather than in standard CI.
API Design
The public surface favors declarative configuration over imperative setup: a @task decorator attaches scheduling defaults (executor, concurrency limit, misfire grace time) directly to a function, and attrs-based TaskParameters/TaskDefaults give consistent, validated keyword arguments across the scheduler, trigger, and data store constructors. Getting started requires only AsyncScheduler() or Scheduler() with no arguments — in-memory defaults are supplied automatically — and moving to a persistent, multi-worker setup is a matter of passing a different data_store and event_broker rather than restructuring application code, which keeps the learning curve gentle for the common cases while still exposing the full abstract interfaces for advanced customization.
Used by 11 apps in this directory
AutoGPT
Automation · Productivity · AI Assistants
Build, deploy, and run autonomous AI agents that automate complex multi-step workflows using a visual block-based graph editor.
Khoj
AI Assistants · Knowledge Management · Productivity
A self-hostable AI second brain that chats with your documents, searches the web, builds custom agents, and runs entirely on your own LLM.
Langflow
AI Agents · AI Development
Build, test, and deploy AI agents and RAG workflows visually with native API and MCP server export.
LiteLLM
AI Development · Developer Tools
Open source AI gateway and Python SDK that gives you one OpenAI-compatible interface to call 100+ LLM providers, with built-in routing, cost tracking, guardrails, and virtual keys.
nao
AI Development · Analytics
Build and deploy an open-source analytics agent that understands your data warehouse and answers business questions in plain English.
OpenPanel
Hosting Control Panel · Devops
Docker-powered web hosting control panel that gives every user a fully isolated environment with dedicated web server, database, and networking — VPS-grade security on shared hardware.
OpenReplay
Analytics
Self-hosted session replay and product analytics suite that lets you see exactly what users do on your web app — without sending data to third parties.
OpenViking
Databases · AI Development
An open-source context database that gives AI agents a unified filesystem for memory, resources, and skills with hierarchical tiered retrieval.
Polar
Ecommerce · Developer Tools · Invoicing Finance
Open source payments infrastructure that turns software into a business — subscriptions, usage-based billing, digital products, and merchant-of-record compliance in one platform.