Let me provide a comprehensive solution addressing all three optimization areas:
API Throttling Limits in D365:
D365 F&O implements multi-tier throttling: user-level (60 requests/minute), tenant-level (varies by license), and Azure APIM limits (typically 100 requests/minute per instance). Your 6 AM failures indicate collision with other scheduled processes. D365 priority throttling favors interactive users over service accounts during business hours (even early morning in some regions).
Incremental Refresh Configuration:
This is your primary solution for 500k row datasets. In Power BI Desktop, configure incremental refresh:
RangeStart = #datetime(2023, 1, 1, 0, 0, 0)
RangeEnd = #datetime(2025, 12, 31, 23, 59, 59)
Archive: 2 years
Incremental: 7 days
Detect data changes: Yes (use ModifiedDateTime column)
Apply filter in Power Query:
`Table.SelectRows(Source, each [ModifiedDateTime] >= RangeStart and [ModifiedDateTime] < RangeEnd)
This reduces daily refresh from 500k rows to approximately 5-10k rows (only recent changes), cutting OData calls by 98% and eliminating throttling issues entirely.
Query Optimization Strategy:
Rewrite your 8 queries with proper OData parameters:
// Before: Full table load with Power BI filtering
RevenueSchedules (500k rows, no filters)
// After: Optimized OData query
RevenueSchedules?$filter=FiscalYear eq 2025 and Status eq 'Active'
&$select=ScheduleId,ContractId,RecognitionDate,Amount,Status
&$top=10000&$skip=0
Implement pagination for large result sets and use $expand judiciously - joining tables in OData is expensive. For your revenue reports, consider creating a denormalized data entity in D365 that combines RevenueSchedules, PerformanceObligations, and ContractDetails. This reduces 8 queries to 2-3 optimized calls.
Additional Optimizations:
- Refresh Timing: Shift to 5:15 AM to avoid 6 AM batch job window, or use 7:30 AM if morning review can wait
- Query Dependencies: Stagger queries using Power Query “Depends On” to serialize OData calls (prevents concurrent throttling)
- DirectQuery Consideration: For real-time data needs, use DirectQuery with aggregations for summary tables, Import mode with incremental refresh for detail tables
- Monitoring: Enable Power BI refresh failure alerts and track API response times in D365 LCS
Immediate Action Plan:
- Enable incremental refresh today (requires Power BI Premium/PPU)
- Add $filter parameters to all queries limiting to current fiscal year + 1 prior year
- Reschedule refresh to 5:15 AM
- Monitor for 1 week - you should see refresh times drop from 45+ minutes to under 10 minutes with zero throttling errors
If you don’t have Premium licensing for incremental refresh, implement query folding with date filters as interim solution - this alone should reduce data volume by 60-70% and resolve most throttling issues.