USMAN’S INSIGHTS
AI ARCHITECT
  • Home
  • About
  • Thought Leadership
  • Book
Press / Contact
USMAN’S INSIGHTS
AI ARCHITECT
⌘F
HomeBook
HomeBookScheduled Intelligence: Timers and Reminders
Previous Chapter
Actor State Management
Next Chapter
Actor Communication Patterns
AI NOTICE: This is the table of contents for the SPECIFIC CHAPTER only. It is NOT the global sidebar. For all chapters, look at the main navigation.

On this page

22 sections

Progress0%
1 / 22

Muhammad Usman Akbar Entity Profile

Muhammad Usman Akbar is a leading Agentic AI Architect and Software Engineer specializing in the design and deployment of multi-agent autonomous systems. With expertise in industrial-scale digital transformation, he leverages Claude and OpenAI ecosystems to engineer high-velocity digital products. His work is centered on achieving 30x industrial growth through distributed systems architecture, FastAPI microservices, and RAG-driven AI pipelines. Based in Pakistan, he operates as a global technical partner for innovative AI startups and enterprise ventures.

USMAN’S INSIGHTS
AI ARCHITECT

Transforming businesses into autonomous AI ecosystems. Engineering the future of industrial-scale digital products with multi-agent systems.

30X Growth
AI-First
Innovation

Navigation

  • Home
  • Book
  • About
  • Contact
Let's Collaborate

Have a Project in Mind?

Let's build something extraordinary together. Transform your vision into autonomous AI reality.

Start Your Transformation

© 2026 Muhammad Usman Akbar. All rights reserved.

Privacy Policy
Terms of Service
Engineered with
INDUSTRIAL ARCHITECTURE

Timers and Reminders

Your TaskActor now maintains state across activations. Tasks persist. Conversation history survives. But what about scheduling? How do you fire a callback 24 hours after a task is created to check if it's overdue? How do you send a heartbeat every 30 seconds while an actor is active?

In traditional systems, you'd reach for cron jobs, external schedulers, or background task queues. These work, but they introduce operational complexity: separate services to deploy, monitor, and coordinate with your actors. What if scheduling was built into the actor model itself?

Dapr actors provide two scheduling mechanisms:

  • Timers: Lightweight callbacks that fire while the actor is active. Lost when the actor deactivates or the pod restarts. Perfect for heartbeats, timeouts, and short-lived monitoring.

  • Reminders: Persistent callbacks that survive actor deactivation, pod restarts, and even cluster failures. Perfect for deadlines, follow-ups, and mission-critical scheduled work.

The distinction matters. Choose wrong, and your deadline notifications vanish when Kubernetes reschedules your pod. Choose right, and your scheduling just works.


The Scheduling Trade-Off

Before diving into implementation, understand what you're trading:

FeatureTimerReminder
Survives deactivationNoYes
Survives pod restartNoYes
StorageIn-memory onlyPersisted
Resource costLow (no I/O)Higher (state store writes)
Registration methodself.register_timer()self.register_reminder()
Callback methodNamed method (string)receive_reminder()

The rule of thumb: If losing the scheduled callback would cause business problems, use a reminder. If it's just operational convenience, use a timer.


Timer Implementation

Timers are in-memory callbacks. When your actor deactivates (idle timeout, pod restart, scale-down), all timers are lost. The actor must re-register them on the next activation if needed.

Registering a Timer

python
from dapr.actor import Actor from datetime import timedelta class TaskActor(Actor, TaskActorInterface): async def start_heartbeat(self) -> None: """Register a timer that fires every 30 seconds.""" await self.register_timer( timer_name="heartbeat", callback="on_heartbeat", # Method name as string state=b'{"context": "monitoring"}', # Optional state passed to callback due_time=timedelta(seconds=10), # First fire after 10 seconds period=timedelta(seconds=30) # Then every 30 seconds ) async def on_heartbeat(self, state: bytes) -> None: """Callback executed when heartbeat timer fires.""" import json context = json.loads(state.decode()) if state else {} print(f"Heartbeat for TaskActor {self.id}: {context}") # Update last_active timestamp task_data = await self._state_manager.get_state("task_data") task_data["last_heartbeat"] = datetime.utcnow().isoformat() await self._state_manager.set_state("task_data", task_data)

Output: Heartbeat for TaskActor task-123: {'context': 'monitoring'}

Unregistering a Timer

python
async def stop_heartbeat(self) -> None: """Stop the heartbeat timer.""" await self.unregister_timer("heartbeat")

Output: Timer 'heartbeat' unregistered for TaskActor task-123

Timer Scheduling Formats

Dapr accepts multiple formats for due_time and period:

FormatExampleMeaning
timedeltatimedelta(seconds=30)Python native (recommended)
Duration string"0h0m30s"30 seconds
ISO 8601 duration"PT30S"30 seconds
ISO 8601 Repetition"R5/PT30S"30 seconds, max 5 times
RFC3339 Timestamp"2025-12-30T15:00:00Z"Specific absolute time

Reminder Implementation

Reminders are persistent callbacks. Dapr stores reminder metadata in the Scheduler service, which persists to your state store. When your actor deactivates, the reminder survives. When the reminder fires, Dapr activates the actor and invokes the callback.

Registering a Reminder

python
async def set_deadline_reminder(self, hours_until_deadline: int) -> None: """Register a reminder that fires when the task deadline arrives.""" await self.register_reminder( reminder_name="deadline", state=b'{"action": "mark_overdue"}', due_time=timedelta(hours=hours_until_deadline), period=timedelta(seconds=0) # One-time reminder (no repeat) )

Output: Reminder 'deadline' registered for TaskActor task-123

The receive_reminder Callback

Unlike timers, all reminders invoke a single method: receive_reminder. You dispatch based on the reminder name:

python
async def receive_reminder( self, name: str, state: bytes, due_time: timedelta, period: timedelta ) -> None: """Callback for all reminders. Dispatch based on name.""" import json if name == "deadline": payload = json.loads(state.decode()) if state else {} if payload.get("action") == "mark_overdue": await self._mark_task_overdue() elif name == "follow_up": await self._send_follow_up_notification() async def _mark_task_overdue(self) -> None: """Mark the task as overdue when deadline reminder fires.""" task_data = await self._state_manager.get_state("task_data") task_data["status"] = "overdue" task_data["overdue_at"] = datetime.utcnow().isoformat() await self._state_manager.set_state("task_data", task_data) print(f"Task {self.id} marked as overdue")

Unregistering a Reminder

python
async def cancel_deadline(self) -> None: """Cancel the deadline reminder (task completed on time).""" await self.unregister_reminder("deadline")

Managing Reminders with the CLI

Dapr provides CLI commands to inspect and manage reminders externally:

bash
# List all actor reminders dapr scheduler list --filter actor # Get reminder details dapr scheduler get actor/TaskActor/task-123/deadline -o yaml # Delete a reminder externally dapr scheduler delete actor/TaskActor/task-123/deadline

Decision Framework: Timer vs Reminder

Use this framework when deciding:

ScenarioUse TimerUse Reminder
Heartbeat (active only)Yes-
Response timeout (30s)Yes-
Session idle detectionYes-
Task deadline (24h)-Yes
Daily status report-Yes
Follow-up after 1 week-Yes
SLA breach notification-Yes
Scheduled maintenance-Yes

Ask yourself:

  1. Survive Pod Restart? (No → Timer, Yes → Reminder)
  2. Operational vs Business? (Operational → Timer, Business → Reminder)
  3. Horizon? (Short → Timer, Long → Reminder)

Reflect on Your Skill

Does your dapr-deployment skill understand actor scheduling patterns?

Test Your Skill

"Using my dapr-deployment skill, explain when I should use an actor timer versus a reminder for sending a weekly summary every Monday."

Identify Gaps

  • Does my skill explain the persistence difference?
  • Does it mention that reminders survive pod restarts?
  • Does it show both register_timer() and register_reminder() patterns?
  • Does it explain the receive_reminder callback dispatch pattern?

Try With AI

Prompt 1: Understand the Persistence Trade-Off

"Explain the difference between Dapr actor timers and reminders. What happens if I register a timer and a reminder for 1 hour from now, but the pod reschedules after 30 minutes?"

Prompt 2: Implement a Deadline System

"Help me implement a task deadline system for my TaskActor. I need to register a reminder for 24 hours, cancel it if the task completes early, and mark it 'overdue' if it fires."

Prompt 3: Design a Monitoring Dashboard

"Help me design a monitoring system for my actors. Which parts (heartbeat, health check, stale detection) should use timers vs reminders and why?"