Data Types
Radhflow has four primitive port types. Every input and output port declares one of these types. The type system enforces compatibility at edge validation time, before any code runs.
A single primitive: string, number, or boolean. Used for configuration parameters, thresholds, flags, and scalar results.
42"enterprise"trueWhen to use: constants, thresholds, feature flags, single extracted values. Produced by value.literal nodes and data.pull (extracts a single value from a table row).
Port declaration:
outputs: threshold: type: value schema: threshold: type: numberRecord
Section titled “Record”A single key-value object. Fields have typed values.
{ "name": "Acme Corp", "score": 87.5, "tier": "enterprise", "active": true}When to use: single entities, configuration objects, API response payloads. A Record is one row of data with named fields.
Port declaration:
outputs: profile: type: record schema: name: type: string required: true score: type: number tier: type: string enum: [enterprise, startup, smb]An ordered list of Records, stored as NDJSON (one JSON object per line). This is the primary data interchange format.
{"email":"a@example.com","score":92,"tier":"high"}{"email":"b@example.com","score":45,"tier":"low"}{"email":"c@example.com","score":78,"tier":"medium"}When to use: datasets, query results, CSV imports, any multi-row data. Most nodes consume and produce Tables.
Port declaration:
inputs: records: type: table schema: email: type: string required: true score: type: number tier: type: stringStream
Section titled “Stream”Semantically identical to Table but signals incremental processing. A Stream is a Table that arrives row-by-row rather than all at once.
{"event":"click","user":"u1","ts":"2025-01-15T10:00:00Z"}{"event":"open","user":"u2","ts":"2025-01-15T10:00:01Z"}When to use: real-time feeds, event logs, webhook payloads. Table and Stream are interchangeable for compatibility checking — a Table output can connect to a Stream input and vice versa.
Port declaration:
inputs: events: type: stream schema: event: type: string user: type: string ts: type: timestampField types
Section titled “Field types”Each field in a schema declares one of these types:
| Type | JSON representation | Example |
|---|---|---|
string | string | "hello" |
number | number (int or float) | 42, 3.14 |
boolean | boolean | true |
timestamp | ISO 8601 string | "2025-01-15T10:00:00Z" |
null | null | null |
list | array | [1, 2, 3] |
record | object | {"a": 1} |
Nested types:
schema: tags: type: list items: type: string address: type: record schema: city: type: string zip: type: stringField modifiers
Section titled “Field modifiers”schema: email: type: string required: true # default: true score: type: number default: 0 # used when field is missing nullable: true # allows null values status: type: string enum: [active, inactive, pending]Type coercion rules
Section titled “Type coercion rules”The type checker enforces these rules at edge validation time:
| Source | Destination | Result | Reason |
|---|---|---|---|
number | number | OK | int and float are both number |
string | timestamp | OK | timestamps are stored as strings |
timestamp | string | OK | reverse also holds |
string | number | Error | no implicit parsing |
number | string | Error | no implicit conversion |
boolean | string | Error | no implicit conversion |
| enum subset | enum | OK | source values are all valid |
| enum superset | enum | Warning | source may produce unexpected values |
| missing required field | — | Error | contract violation |
| extra fields | — | OK | consumer ignores extras |
Port type compatibility
Section titled “Port type compatibility”| Source port | Dest port | Compatible | Notes |
|---|---|---|---|
table | table | Yes | Standard connection |
stream | table | Yes | Interchangeable |
table | stream | Yes | Interchangeable |
table | value | Yes | Auto-pull from first row |
value | value | Yes | Standard connection |
record | record | Yes | Standard connection |
value | table | No | Type mismatch |
record | table | No | Type mismatch |
How types flow through edges
Section titled “How types flow through edges”Each edge connects a source port to a destination port. The type checker validates that:
- The port types are compatible (see table above).
- Every required field in the destination schema exists in the source schema.
- Field types match (using coercion rules).
- Enum constraints are satisfied.
Extra fields in the source are ignored — the destination only sees what it declares. This makes pipelines resilient to upstream schema additions.