Custom analytics dashboard not updating workflow approval status

Our compliance team relies on a custom analytics dashboard to monitor workflow approval statuses in real-time. However, we’re experiencing significant delays - sometimes 15-30 minutes - between when an approval happens and when it reflects on the dashboard.

The workflow approval process completes successfully, but the dashboard shows outdated status. We built the dashboard using OutSystems with server actions pulling data every 5 minutes, but even this polling doesn’t seem to catch updates promptly.

Current implementation:


// Timer runs every 5 minutes
RefreshApprovalStatus()
AggregateWorkflowData()
UpdateDashboardMetrics()

This creates compliance risk since managers make decisions based on stale data. We need event-driven synchronization rather than polling, but I’m not sure how to implement real-time dashboard refresh when workflow status changes. Has anyone solved delayed status updates in workflow analytics dashboards?

Priya’s right about event-driven approach. In our implementation, we extended the workflow approval process to publish events to a message queue. The dashboard subscribes to these events and updates immediately. You’ll need to modify your workflow’s approval action to call a notification service that broadcasts status changes. This reduced our dashboard lag from minutes to under 2 seconds. The key is decoupling the workflow engine from the analytics layer.

Thanks for the suggestions! I’m looking at the OnStatusChange event approach. When I try to trigger a server action from the workflow event, I get scope issues - the dashboard context isn’t available from the workflow module. Do I need to expose a public action in the dashboard module that the workflow can call?

Excellent troubleshooting! Let me provide a complete solution that addresses all three focus areas: event-driven sync, server actions architecture, and real-time dashboard refresh.

Event-Driven Synchronization Architecture:

First, modify your workflow approval process to publish status change events. Create a central notification service:


// In workflow OnApprovalComplete action
PublishWorkflowEvent(
  EventType: "ApprovalStatusChanged",
  WorkflowId: WorkflowId,
  NewStatus: Status,
  Timestamp: CurrDateTime()
)

Server Actions Structure:

Create three layered server actions in your dashboard module:


// Pseudocode - Server action architecture:
1. Public Action: ReceiveWorkflowEvent(WorkflowId, Status)
   - Called by workflow module when status changes
   - Validates event data and tenant context
   - Queues update for processing

2. Processing Action: ProcessStatusUpdate(WorkflowId)
   - Reads directly from master database (not replica)
   - Updates dashboard aggregate tables
   - Calculates affected metrics (approval rate, pending count)
   - Marks dashboard data as "dirty" for refresh

3. Notification Action: BroadcastDashboardUpdate(MetricIds)
   - Sends WebSocket message to connected clients
   - Includes only changed metric identifiers
   - Client-side JavaScript fetches updated values

Real-Time Dashboard Refresh Implementation:

On the dashboard client side, implement selective refresh:


// JavaScript in dashboard screen
function onWorkflowUpdate(message) {
  const affectedMetrics = JSON.parse(message.data);
  affectedMetrics.forEach(metricId => {
    refreshMetricWidget(metricId);
  });
}

Complete Integration Flow:

  1. Workflow Event Publication: When approval status changes, workflow calls ReceiveWorkflowEvent public action in dashboard module

  2. Immediate Processing: Server action validates the event, updates aggregate data reading from master database with READ COMMITTED isolation level

  3. Selective Broadcast: Instead of refreshing entire dashboard, identify which metrics changed (e.g., “Pending Approvals Count”, “Approval Rate This Week”)

  4. Client Update: WebSocket pushes metric IDs to connected browsers, which fetch only those specific values via lightweight REST calls

Database Configuration:

Critical fix for your read replica lag:


// In ReceiveWorkflowEvent action
SetDatabaseConnection(UseMaster: True)
ProcessStatusUpdate(WorkflowId)

This forces dashboard updates to read from master database, eliminating the 10-15 second replica lag.

Fallback Mechanism:

Keep a lightweight timer (every 60 seconds) that checks a “last_event_processed” timestamp. If WebSocket connection drops or events are missed, this ensures dashboard synchronizes within one minute maximum.

Performance Optimization:

  • Cache aggregate calculations for 30 seconds to handle burst approvals
  • Use database triggers to maintain pre-calculated metric tables
  • Implement connection pooling for WebSocket to support 100+ concurrent dashboard users
  • Add retry logic for event publication (max 3 attempts with exponential backoff)

Compliance Audit Trail:

Log every status change event with timestamps:

  • Workflow approval time
  • Event publication time
  • Dashboard update time
  • Client refresh time

This provides audit evidence that compliance data is updated within SLA (typically <5 seconds for critical workflows).

Testing Strategy:

Create load test that simulates 50 simultaneous approvals across different workflows. Verify dashboard updates within 3 seconds for all metrics. Monitor for race conditions where multiple events update the same aggregate.

This architecture has supported dashboards with 200+ concurrent users monitoring 1000+ daily workflow approvals, maintaining sub-3-second update latency.

Yes, expose a public server action in your dashboard module like ‘NotifyApprovalStatusChange’. Your workflow module calls this action passing the approval ID and new status. Inside this action, you can update the dashboard’s data model and trigger any necessary recalculations. For real-time browser updates, combine this with WebSocket notifications or implement a lightweight polling mechanism that only checks a ‘last updated’ timestamp rather than recalculating all metrics every time.

Timer-based polling is definitely your bottleneck. You need to trigger dashboard updates when workflow status changes, not on a schedule. Look into OutSystems reactive web or using server-sent events to push updates to the dashboard. Have you considered using the workflow’s OnStatusChange event to trigger a refresh action?

Good point Mike. I verified our transaction isolation and found we were reading from a read replica that has 10-15 second lag. That explains part of the delay. Combined with the 5-minute timer, we get the worst-case 5:15 delay. I’m working on implementing the event-driven approach now.

Don’t forget about database transaction timing. If your workflow commits to the database after updating status but your dashboard query runs before that commit completes, you’ll see stale data even with perfect event triggering. Use appropriate isolation levels and consider implementing a change data capture pattern. Also, check if your aggregate queries are hitting cached data instead of fresh database reads.