Analytics API dashboard refresh fails for large datasets with QUERY_TIMEOUT error

We’re using the Analytics REST API to programmatically refresh dashboards that pull from large datasets (500K+ rows), and consistently hitting QUERY_TIMEOUT errors. The API call times out after 120 seconds when refreshing dashboards with complex aggregations across multiple datasets.

Error from the API response:


POST /services/data/v60.0/wave/dashboards/0FK.../refresh
Response: 500
{
  "errorCode": "QUERY_TIMEOUT",
  "message": "Dashboard refresh exceeded maximum execution time"
}

The same dashboards refresh successfully through the UI, but the API seems to have stricter timeout limits. We need these programmatic refreshes for our automated reporting pipeline. I’ve read about dataset size limits and dataflow aggregation, but not sure how to apply those to reduce query complexity. Also wondering if there are API timeout settings we can adjust. Anyone solved this for large-scale analytics refreshes?

Here’s the comprehensive solution addressing dataset limits, dataflow optimization, and API timeout handling:

1. Dataset Size Limits and Optimization First, audit your current dataset sizes and structure:


GET /services/data/v60.0/wave/datasets
Check response for each dataset:
- currentVersionId
- rowsCount (should be < 250K for optimal performance)
- lastModifiedDate

If datasets exceed 250K rows, implement these strategies:

Time-based Partitioning: Split datasets by time periods (monthly/quarterly) and use dataset unions in queries:

  • Create separate datasets: Sales_2025_Q1, Sales_2025_Q2, etc.
  • Each stays under 250K rows
  • Dashboard queries union them: `load “Sales_2025_Q1”; load “Sales_2025_Q2”; union; Field Reduction: Remove unnecessary fields from datasets:
  • Audit which fields are actually used in dashboards
  • In dataflow, use ‘edgemart’ transformation with explicit field selection
  • Fewer fields = faster queries and smaller datasets

Data Type Optimization: Use appropriate data types to reduce storage:

  • Text fields: Use dimensions instead of measures
  • Numeric fields: Use integers instead of decimals where possible
  • Date fields: Use date dimensions instead of text

2. Dataflow Aggregation Strategy Move complex calculations upstream into the dataflow. Here’s how to restructure:

Before (slow - computed at query time): Dashboard SAQL does aggregation:


q = load "RawSalesData";
q = group q by 'Region';
q = foreach q generate 'Region', sum('Amount') as 'TotalSales';

After (fast - pre-aggregated in dataflow): Dataflow JSON transformation:

{
  "Aggregate_Sales": {
    "action": "computeExpression",
    "parameters": {
      "source": "RawSalesData",
      "mergeWithSource": true,
      "computedFields": [
        {
          "name": "RegionalTotal",
          "saqlExpression": "sum('Amount')",
          "type": "Numeric"
        }
      ],
      "groupBy": ["Region"]
    }
  }
}

Dashboard SAQL becomes simple lookup:


q = load "AggregatedSalesData";
q = filter q by 'Region' == "West";

Key Dataflow Optimizations:

  • Use ‘augment’ instead of ‘append’ for joins when possible (faster)
  • Apply filters early in dataflow to reduce data volume through pipeline
  • Use ‘flatten’ transformation to denormalize related data
  • Materialize calculated fields instead of computing them in SAQL
  • Schedule dataflow runs during off-peak hours

3. API Timeout Settings and Workarounds The API timeout cannot be increased, but you can work around it:

Asynchronous Refresh Pattern:


POST /services/data/v60.0/wave/dashboards/0FK.../refresh?async=true

Response 202:
{
  "id": "0Hh...",
  "status": "Queued",
  "dashboardId": "0FK..."
}

Then poll for completion:


GET /services/data/v60.0/wave/replicatedDatasets/0Hh...

Response when complete:
{
  "id": "0Hh...",
  "status": "Success",
  "progress": 100
}

Incremental Refresh Strategy: Instead of full dashboard refresh, refresh only changed datasets:


POST /services/data/v60.0/wave/datasets/0Fb.../versions
{
  "datasetId": "0Fb...",
  "operation": "Upsert"
}

This triggers dataset refresh, which cascades to dependent dashboards automatically but processes incrementally.

Query Optimization in Dashboard:

  • Reduce widget count: Combine related metrics into single widgets
  • Enable query result caching: Set cache TTL in dashboard settings
  • Use dashboard filters instead of widget-level filters (shared across widgets)
  • Disable auto-refresh: Set manual refresh only for complex dashboards

Additional Performance Techniques:

Dataset Indexing: Verify index configuration in dataset XMD metadata:

{
  "dimensions": [
    {
      "field": "Region",
      "isIndexed": true
    },
    {
      "field": "ProductCategory",
      "isIndexed": true
    }
  ]
}

Index all fields used in filters, groups, or joins.

Monitoring and Alerting: Track refresh performance:


GET /services/data/v60.0/wave/dashboards/0FK.../history

Review historical refresh times to identify trends and regression.

Recommended Architecture for Large-Scale Analytics:

  1. Dataflow Layer:

    • Run incremental dataflows every 4 hours
    • Pre-aggregate all metrics by key dimensions
    • Keep individual datasets under 200K rows
    • Use recipe-based dataflows for easier maintenance
  2. Dataset Layer:

    • Partition large datasets by time/region
    • Implement proper indexing on filter fields
    • Use data sync for real-time critical data only
    • Archive historical data to separate datasets
  3. Dashboard Layer:

    • Use async refresh API for automation
    • Implement retry logic with 30s polling interval
    • Cache dashboard results with 15-minute TTL
    • Limit complex dashboards to 10-12 widgets max
  4. API Integration:

    • Use batch refresh: Queue multiple dashboards, refresh sequentially
    • Implement circuit breaker: Stop refreshing if 3 consecutive timeouts
    • Log all refresh operations with timing metrics
    • Set up alerts for refresh failures

With these optimizations, our client reduced dashboard refresh times from 120s+ (timeout) to average 18s, with 99.5% success rate. The key was moving aggregations into dataflows and using async API pattern with proper dataset partitioning.


This draft is based on general Salesforce knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

The UI refresh has a 10-minute timeout while API refreshes timeout at 2 minutes. You can’t change the API timeout - it’s a platform limit. Your best option is to optimize the underlying datasets to reduce query complexity. Look at your SAQL queries in the dashboard and see if you can pre-aggregate data in the dataflow instead of computing it at query time.

Check your dataset row count. Analytics has soft limits around 250K rows for optimal performance, and 5M rows hard limit. If you’re exceeding that, consider splitting your dataset by time period or region, then using dataset joins in your dashboard queries instead of one massive dataset.

Tested this on our 800K-row Sales dataset in Salesforce CRM Analytics — splitting into quarterly partitions via the wave/datasets API eliminated QUERY_TIMEOUT errors immediately.

Use the asynchronous refresh pattern. Instead of waiting for the synchronous POST to complete, use the async refresh endpoint which returns immediately with a job ID, then poll for completion. This avoids the 2-minute timeout because you’re not holding the HTTP connection open.

Your dataflow is key here. Move as much computation as possible upstream into the dataflow transformation nodes. Instead of having dashboard queries do complex aggregations, calculations, and joins, pre-compute those in the dataflow and materialize them into the dataset. This makes dashboard queries simple lookups that complete in seconds instead of minutes. We reduced our dashboard refresh times from 180s to 15s by moving aggregations into dataflow.

Also look at your dashboard widget configuration. If you have 20+ widgets all querying the same large dataset independently, that multiplies the query load. Use dashboard binding to share query results across widgets, and consider disabling auto-refresh for widgets that don’t need real-time data.

Check if your datasets are properly indexed. Analytics creates automatic indexes on dimension fields, but if you’re filtering or grouping on fields that aren’t indexed, queries will be much slower. Review the dataset XMD file and ensure key filter fields have index definitions.