Design a Distributed Job Scheduler with Run Logs and Exactly-Once Execution
AmazonSoftware Engineer · OnsiteLast updated
Design a highly available distributed job scheduler that handles one-time and recurring jobs, collects execution logs, and rigorously addresses the practical boundaries of exactly-once execution.
Scenario
You are asked to design a scalable distributed job scheduler for a multi-tenant cloud platform (similar to AWS EventBridge combined with AWS Batch). The platform allows users to schedule arbitrary compute tasks, monitors their execution across a dynamic pool of worker machines, and stores detailed execution logs for auditing and debugging.
A critical requirement emphasized by stakeholders is handling failure modes gracefully: workers may crash mid-task, network partitions will occur, and duplicate executions must be strictly controlled or prevented.
Requirements
Functional Requirements
- Job Definition & Scheduling: Support one-off jobs (execute at timestamp
T) and recurring jobs (cron-based schedules). - Job Execution: Assign jobs to a pool of distributed workers based on priority and availability.
- Status & Run Logs: Capture real-time status transitions (e.g.,
SCHEDULED,RUNNING,COMPLETED,FAILED) and ingest/store output logs (stdout/stderr) for each execution run. - Cancellation & Retries: Allow users to abort scheduled or running jobs, and configure retry policies with exponential backoff on failure.
- Delivery & Execution Guarantees: Address the client expectation of "exactly-once execution" and design mechanisms (e.g., distributed leases, fencing tokens, idempotency) to handle duplicates and split-brain scenarios.
Non-Functional Requirements
- Scalability: Support 100 million registered job definitions, triggering up to 100,000 executions per minute at peak (~2,000 executions/second).
- Dispatch Latency: Jobs should begin executing within 5 seconds of their scheduled time.
- Log Retention & Durability: Run logs must be durable and retrievable for at least 30 days.
- Fault Tolerance: No single point of failure; scheduler nodes or workers crashing must not result in permanently orphaned or duplicate-executed jobs.
What Your Design Should Cover
- Core Architecture & Component Flow: Scheduler coordinator, time-bucketed delay queues, worker pools, and heartbeat managers.
- Data Model & State Management: Schema for job metadata, execution runs, and schedule triggers.
- Exactly-Once vs. At-Least-Once Analysis: Realistic trade-offs regarding distributed consensus, fencing tokens, and idempotent execution keys.
- Log Ingestion Pipeline: Architecture for handling bursty log streams from workers without impacting scheduling latency.
- Edge Cases: Handling worker network isolation, clock skew across nodes, and worker crash during log flushing.
Hints
Hint 1
Differentiate between 'exactly-once delivery' across the network (theoretically impossible under arbitrary partitions) and 'effectively-once execution' achieved via monotonically increasing fencing tokens and worker-side idempotency.
Hint 2
Partition scheduled jobs using time buckets (e.g., minute-level buckets) in a persistent key-value or document store to avoid full-table scans when polling for runnable tasks.
Hint 3
Decouple the log streaming pipeline from the scheduler control plane using an append-only distributed log (e.g., Kafka) or direct-to-object-storage chunked uploads to prevent log ingestion from starving task dispatching.
Follow-up questions
- How does your design address clock skew across scheduler instances when evaluating cron expressions and triggering jobs?
- If a worker loses its lease due to a temporary network partition but continues running the task locally, how do you prevent it from corrupting downstream state when a replacement worker is spawned?
- How would you scale log search if users need to perform full-text or regex queries across petabytes of historical execution logs?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.