I’ve implemented several IoT billing systems and this is a common pattern. Here’s a comprehensive solution addressing all three aspects:
Custom Attribute Extraction:
Modify your IoT Rules Engine SQL to handle schema variations robustly:
SELECT
coalesce(tenant_id, metadata.tenant_id, 'UNKNOWN') as tenant_id,
cast(data_volume as Decimal) as data_volume,
timestamp,
topic(2) as device_id
FROM 'device/+/telemetry'
WHERE data_volume IS NOT NULL
The coalesce() function checks multiple paths and provides a fallback. Using ‘UNKNOWN’ lets you identify and quarantine problematic messages.
Multi-tenant Charge Allocation:
In your billing Lambda, implement a two-phase validation:
if tenant_id == 'UNKNOWN':
publish_to_dlq(message)
return
tenant_config = get_tenant_billing_config(tenant_id)
charge = calculate_charge(data_volume, tenant_config['rate'])
Create a DLQ (Dead Letter Queue) topic for failed extractions. This prevents revenue leakage while you investigate root causes.
IoT Rules Engine SQL Syntax Best Practices:
- Always use explicit type casting for numeric fields (
cast(data_volume as Decimal))
- Add the device identifier from the topic path using
topic() function for audit trails
- Use
IS NOT NULL instead of > 0 to catch extraction failures early
- Enable CloudWatch Logs for your rule to see actual SQL execution results
For the $12K revenue leakage, query your CloudWatch Logs Insights with:
fields @timestamp, tenant_id, data_volume
| filter tenant_id = 'UNKNOWN' or tenant_id is null
| stats count() by bin(5m)
This shows when extractions failed. Cross-reference with your device deployment history to identify which firmware versions need updates.
Finally, implement idempotency in your billing Lambda using DynamoDB to track processed message IDs. This prevents double-charging when you reprocess the missed messages. Set up a separate reconciliation job that runs daily to compare IoT Core message counts against billing records - any discrepancy triggers alerts.
The key is treating billing as a critical path with proper error handling, monitoring, and reconciliation rather than assuming the happy path always works.