This page lists every ${…} variable KafkIO understands, with its arguments, what it gives and what
happens when one is written wrongly. Variables work in the Produce Message(s)
dialog while '${variable}' substitution is ticked: in the key, the message, and
header keys and values. How to use them while producing (the option, the counter across a batch, templates) is
in Producing Messages.
All variables
Arguments in italics are optional. The example results are real ones, from 26 October 2026 at 12:07.
| Variable | Gives | Example result |
|---|---|---|
${counter} | 1, 2, 3... one more each time it's used (Counter) | 1 |
${random.int:min:max} | A random whole number (Random numbers) | ${random.int:60:300} → 187 |
${random.double:min:max} | A random decimal number | ${random.double:-5:5} → -2.6552469347229133 |
${random.string:min:max} | Random letters and digits (Random strings and UUIDs) | ${random.string:6:6} → WZ8EsC |
${random.uuid} | A random UUID | efe1ca4c-f714-4b32-b270-76c9adaa37e9 |
${current.date:format} | Today's date (Dates and times) | 2026-10-26 |
${current.datetime:format} | The date and time now | 2026-10-26T12:07:16.444184200 |
${epoch.seconds} | Seconds since 1 January 1970 UTC | 1793016436 |
${epoch.millis} | Milliseconds since 1 January 1970 UTC | 1793016436444 |
Syntax
A variable is ${, its name, any arguments each after a colon, and }:
${random.uuid}, ${random.int:1000}, ${random.int:60:300},
${current.date:dd/MM/yyyy}. A variable can sit anywhere in the text, alone or inside other text:
ORD-${current.date:yyyyMMdd}-${counter} gives ORD-20261026-1.
- Exact names. Names are case-sensitive and can't contain spaces:
${Counter}and${ counter }are not variables. Anything KafkIO doesn't recognise, such as${user.name}, is sent exactly as typed, without an error. - Arguments only where listed.
${counter},${random.uuid}and the epoch variables take none: with one (${counter:5}) they aren't recognised and stay as typed. The random variables take at most two; with three or more,random.int,random.doubleandrandom.stringignore them all and behave as if they had none. - No variables inside variables.
${random.int:${counter}:9}is an error. - A literal
${. Double the dollar sign:$${counter}is sent as${counter}. To send a whole message full of${…}text unchanged, untick '${variable}' substitution instead.
Variables are replaced in the text you typed, before the serializer turns it into bytes, so the result must
still be valid for the serializer. In JSON (or Avro and Protobuf written as JSON), leave a variable unquoted
where a number belongs and quote it where a string belongs:
"amount": ${random.int:5:500}, "id": "${random.uuid}".
Every message is built afresh, so each one gets new random values and the current time as it's built. The key is filled in first, then the message, then the headers (each header's key, then its value).
Counter
${counter} starts at 1 every time you click the send button (or Test
in the examples window), and goes up by one each time it's used, wherever
it's used. A batch of ten messages with one ${counter} in the message gets 1 to 10; with a counter
in both the key and the message, the first message gets 1 and 2, the next 3 and 4.
Producing Messages shows how to keep
them matching.
There's no starting value or step: ${counter} is always 1, 2, 3... for each send. For numbers that
carry on from earlier batches, use ${epoch.millis} (always increasing, though not by one) or put
a fixed prefix in front: batch2-${counter}.
Random numbers
| Variable | Gives |
|---|---|
${random.int} | A whole number from 0 to 2,147,483,646 |
${random.int:min} | A whole number from min to 2,147,483,646 |
${random.int:min:max} | A whole number from min up to, but not including, max; exactly min when the two are equal |
${random.double}, ${random.double:min} | A decimal number
from 1 (or min) up to the largest number Java can hold, so nearly always something like
1.5667141473952902E308. Give a range instead. |
${random.double:min:max} | A decimal number from min up to, but not including, max; exactly min when the two are equal |
- The maximum is never reached.
${random.int:1:7}gives 1 to 6, like a dice roll;${random.int:1:2}is always 1. Add one to the maximum you want:customer-${random.int:1:21}spreads messages overcustomer-1tocustomer-20. (The examples window's own notes say "<= 300"; the code stops one short.) - Negative numbers work:
${random.int:-10:11}gives -10 to 10.random.intarguments must be whole numbers between -2,147,483,648 and 2,147,483,647;random.doubleaccepts decimals (${random.double:0.5:1.5}). - Decimals come with every digit.
random.doubleprints as many decimal places as the number has (37.48120934571266), and numbers of 10 million or more in E notation (4.513726254437281E7). For a price with two decimals, build it from whole numbers:${random.int:1:100}.${random.int:0:10}${random.int:0:10}gives1.00to99.99.
Random strings and UUIDs
| Variable | Gives |
|---|---|
${random.string} | 1 to 63 random characters |
${random.string:min} | min to 63 characters (min can be at most 64, which gives exactly 64) |
${random.string:min:max} | min up to, but not including,
max characters; exactly min when the two are equal, so
${random.string:8:8} is always 8 characters. No upper limit:
${random.string:1000:1000} works. |
${random.uuid} | A random (version 4) UUID, 36 characters with dashes |
Random strings use only the letters A-Z, a-z and the digits
0-9, so they're safe inside JSON strings, CSV and header values.
${random.string:0:0} gives an empty string.
Dates and times
| Variable | Gives |
|---|---|
${current.date} | Today's date as yyyy-MM-dd:
2026-10-26 |
${current.date:format} | Today's date in your
format, which can't include a time:
${current.date:EEEE d MMMM yyyy} gives Monday 26 October 2026 |
${current.datetime} | The date and time with nine decimal places of seconds:
2026-10-26T12:07:16.444184200 |
${current.datetime:format} | The date and time in your format:
${current.datetime:yyyy-MM-dd'T'HH:mm:ss.SSS} gives
2026-10-26T12:07:16.444 |
${epoch.seconds} | Whole seconds since 1 January 1970 UTC |
${epoch.millis} | Milliseconds since 1 January 1970 UTC, the form Kafka uses for message timestamps |
current.date and current.datetime use your computer's local time and carry no time
zone, so no format can show one (it's an error). For a time that means
the same everywhere, send ${epoch.millis} or ${epoch.seconds}. Month and day names,
and the AM/PM marker, follow KafkIO's language and your
computer's region: with English in Ireland, h:mm a gives 12:07 p.m.
Date and time format patterns
Formats are Java date-time patterns: letters stand for parts of the date, and the number of letters sets the style. The common ones, as they print on Monday 26 October 2026 at 12:07:16.444 (14:07 for the hours):
| Pattern | Meaning | Gives |
|---|---|---|
yyyy, yy | Year | 2026, 26 |
M, MM, MMM, MMMM | Month | 10, 10, Oct, October |
d, dd | Day of the month (dd pads to two digits) |
26, 26 (on the 5th: 5, 05) |
EEE, EEEE | Day of the week | Mon, Monday |
D | Day of the year | 299 |
w | Week of the year (numbering depends on your region) | 44 |
Q, QQQ | Quarter | 4, Q4 |
HH | Hour, 00-23 | 14 |
hh, h | Hour, 1-12 (use with a) | 02, 2 |
a | AM/PM marker | p.m. or PM, by region |
mm | Minutes | 07 |
ss | Seconds | 16 |
SSS, SSSSSS | Fraction of a second: milliseconds, microseconds | 444, 444184 |
'text' | Literal text | 'T' → T,
'week' w → week 44 |
'' | A single quote | ''yy → '26 |
Spaces and punctuation such as - / : , . and ( ) print as they are. Every unquoted
letter is a pattern letter, so put words in single quotes, as in yyyy-MM-dd'T'HH:mm:ss. The full
list is in Java's
DateTimeFormatter documentation.
MM is the month and mm the minutes;
HH is 24-hour and hh 12-hour. YYYY is a week-based year, which is
a year off for a few days around New Year (on 29 December 2025 it already gives 2026): use
yyyy.Trying variables out
Before sending anything, test a variable or a date format in Variables Substitution Examples: click Examples next to '${variable}' substitution in the Produce dialog (The examples window). Type your own text in the top box and click 1 Test; the counter starts again at 1 on every test.
- Test: substitutes the top box again, with fresh random values and the time now.
When a variable is wrong
A mistake in a recognised variable's arguments stops the send: an Exception Details window opens with Error sending message(s) and the reason, and no message is sent (the same reason appears in the examples window after Test). The reason is Java's, and doesn't say which variable failed:
| You wrote | What happens |
|---|---|
${Counter}, ${ counter }, ${user.name},
${counter:5} | Not a variable: sent as typed |
${random.int:1.5}, ${random.int:abc} |
For input string: "1.5" (random.int needs whole numbers) |
${random.int:5:1}, ${random.string:100} |
For example min (100) must be less than or equal to max (64) |
${random.int:${counter}:9} | For input string: "${counter" |
${current.date:HH:mm} | Unsupported field: HourOfDay: a date has
no time; use current.datetime |
${current.datetime:XXX}, ${current.datetime:z} |
Unsupported field: OffsetSeconds, Unable to extract ZoneId from temporal:
no time zones (Dates and times) |
${current.date:today} | Unknown pattern letter: t: quote words
('today') |
Examples
- A unique key per message:
${random.uuid}, ororder-${counter}when the key is the only place using the counter. - Messages spread over 20 keys, and so across partitions:
customer-${random.int:1:21}. - An ISO 8601 local timestamp:
"${current.datetime:yyyy-MM-dd'T'HH:mm:ss.SSS}". - An event time as a number:
${epoch.millis}. - A price:
${random.int:1:100}.${random.int:0:10}${random.int:0:10}. - A fixed-length code:
${random.string:6:6}. - A dated order number:
ORD-${current.date:yyyyMMdd}-${counter}. - A trace header: header key
trace-id, value${random.uuid}.