OData connection timeout when fetching device usage data for billing engine integration

OData requests to fetch device usage data from the IoT Time Series service are timing out when we try to generate monthly billing reports. The requests work fine for small date ranges (1-2 days) but fail with timeout errors for monthly data.

Query example:


GET /DeviceUsage?$filter=deviceId eq 'METER_123' and timestamp ge 2025-01-01 and timestamp le 2025-01-31

We’re hitting 60-second timeouts on datasets with ~50K records per device. This is causing billing delays as we can’t aggregate usage data for invoicing. Is there a better way to structure these queries or configure timeout settings for large result sets?

Good suggestions. I tried adding $top=1000 and it helped, but pagination through 50 pages per device is still slow. The timeout configuration seems hardcoded - I couldn’t find where to adjust it in the IoT service settings. Is there a configuration parameter for OData request timeout?

Also consider using $select to limit the fields returned. If you only need usage values and timestamps for billing, don’t fetch all device metadata. Something like: $select=timestamp,usageValue,deviceId can significantly reduce payload size and improve performance.

Consider using aggregation at the API level instead of fetching raw records. The IoT Time Series service supports aggregation functions. Use $apply with aggregate functions to get pre-calculated sums directly from the service rather than pulling all records and aggregating client-side. This reduces data transfer and processing time dramatically.

The timeout is configurable but not through the UI. You need to set environment variables for the OData service. In Cloud Foundry, update the manifest.yml with REQUEST_TIMEOUT_SECONDS parameter. Default is 60, you can increase to 120 or 180. However, increasing timeout is just masking the problem - you really should optimize the query approach rather than waiting longer for inefficient queries.

Your billing query approach needs a complete redesign to handle this data volume efficiently. Let me address all three optimization areas:

OData Query Optimization: Replace your single large query with an aggregation-based approach using $apply:


GET /DeviceUsage?$filter=deviceId eq 'METER_123' and timestamp ge 2025-01-01 and timestamp le 2025-01-31
  &$apply=groupby((deviceId),aggregate(usageValue with sum as totalUsage))

This returns a single aggregated row instead of 50K records. For daily breakdowns, add date grouping:


&$apply=groupby((deviceId,date(timestamp)),aggregate(usageValue with sum as dailyUsage))

This returns 31 rows (one per day) instead of 50K, reducing response time from 60+ seconds to under 2 seconds.

Timeout Configuration: While you can increase timeouts, the proper solution is fixing the query. However, for legitimate cases requiring longer execution:

  1. Update the destination configuration (if using SAP BTP):
{
  "timeout": 180000,
  "readTimeout": 180000
}
  1. For direct service calls, set HTTP client timeout in your application:
HttpClient.newBuilder()
  .connectTimeout(Duration.ofSeconds(30))
  .build();
  1. IoT Time Series service has a hard limit of 300 seconds that cannot be exceeded. Beyond this, you must use pagination.

Pagination Implementation: For scenarios requiring raw data (not aggregates), implement proper pagination with server-side cursor:


// Initial request
GET /DeviceUsage?$filter=... &$top=1000 &$orderby=timestamp

// Subsequent requests use skiptoken from @odata.nextLink
GET /DeviceUsage?$filter=... &$skiptoken={token}

Implement this in your billing service:


List<Usage> allRecords = new ArrayList<>();
String nextUrl = initialQuery;
while (nextUrl != null) {
  Response resp = httpClient.get(nextUrl);
  allRecords.addAll(resp.getValue());
  nextUrl = resp.getNextLink();
}

Recommended Billing Architecture: For monthly billing, pre-aggregate data using scheduled background jobs:

  1. Create a daily aggregation job that runs at midnight
  2. Store daily summaries in a separate billing table
  3. Monthly billing queries only aggregate 31 daily records instead of 50K raw records
  4. Use IoT Business Rules to trigger aggregation on data arrival

This approach reduces monthly billing report generation from minutes to seconds. The aggregation overhead is distributed throughout the month rather than concentrated at billing time.

Implement the $apply aggregation first - it will immediately solve your timeout issue for standard billing use cases.