An Azure real-time analytics service designed for mission-critical workloads.
Hi @GP13
Thanks for the detailed repro, this is actually expected behavior, not a bug or a recent change in ASA.
What's happening
In Azure Stream Analytics, the record (nested object) type is only supported as an output for JSON and Avro — it is not in the type-mapping matrix for Parquet. Parquet/Avro outputs are treated as strongly-typed / schema-on-write, so nested columns like before, after, and source can't be materialized and come out as null. Scalar fields (op, ts_ms) work fine because they're simple types. That's also why:
-
TRY_CAST(... AS record)doesn't help — the column staysrecord-typed. -
TRY_CAST(... AS nvarchar(max))on a nested object doesn't JSON-stringify it either. - JSON output works, because
recordmaps directly to a JSON object.
Refs:
- Outputs from Azure Stream Analytics: https://learn.microsoft.com/azure/stream-analytics/stream-analytics-define-outputs#avro-and-parquet-file-splitting-behavior
- ASA Data Types – type mappings: https://learn.microsoft.com/stream-analytics-query/data-types-azure-stream-analytics#type-mappings-and-serialization-formats
Two ways to fix it
Option 1 (recommended) — Flatten before writing to Parquet.
Project each nested field as its own scalar column using dot notation:
SELECT
-- before.*
TRY_CAST([before].[id] AS bigint) AS before_id,
TRY_CAST([before].[field1] AS nvarchar(max)) AS before_field1,
TRY_CAST([before].[field2] AS bigint) AS before_field2,
-- after.*
TRY_CAST([after].[id] AS bigint) AS after_id,
TRY_CAST([after].[field1] AS nvarchar(max)) AS after_field1,
TRY_CAST([after].[field2] AS bigint) AS after_field2,
-- source.*
TRY_CAST([source].[version] AS nvarchar(max)) AS source_version,
TRY_CAST([source].[db] AS nvarchar(max)) AS source_db,
TRY_CAST([source].[table] AS nvarchar(max)) AS source_table,
op,
TRY_CAST(ts_ms AS bigint) AS ts_ms
INTO [ParquetOutput]
FROM [eventhub-input]
For inserts (op = 'c'), the before_* columns will naturally be null — that's correct Debezium semantics.
Option 2 — Keep the full nested envelope.
If you must preserve before / after / source as nested structs, ASA isn't the right serializer. Write JSON to ADLS Gen2 from ASA, then convert to Parquet downstream in Databricks / Synapse Spark / Fabric where nested Parquet structs are fully supported. Or, for pure capture, use Event Hubs Capture directly.
Quick answers to your 3 questions
- Serialize nested records to Parquet in ASA? Not as nested structs. Flatten to scalars (Option 1) or convert downstream (Option 2).
- Is
TRY_CAST AS recordsupported for Parquet? No.recordisn't in the Parquet output mapping, so it lands as null. Documented limitation. - Has ASA changed? No,
record → Parquetwas never in the supported matrix. The earlier job likely used JSON/Avro or a simpler payload that happened to flatten cleanly.
Please try Option 1 and let us know how the flattened columns look in the Parquet output. Happy to help further if you want to preserve the full nested structure.