Document structure

A DNML request file is a TOML document. It has some keys for the full request, then one block for each operation.

version = "1.0"
name = "reconcile-orders"
description = "Find unpaid orders and flag them."

[variables]
status = "UNPAID"

[defaults]
profileName = "commerce-dev"
region = "ap-southeast-2"

[execution]
onError = "stop"

[[dynamodb.query]]
name = "Find unpaid"
# ...keys of the query

[[dynamodb.update]]
name = "Flag order"
dependsOn = "Find unpaid"
# ...keys of the update

Top-Level Keys

KeyTypeRequiredPurpose
versionstringYes"1.0". See Versioning.
namestringYesThe same as the filename. See Naming rules.
descriptionstringNoWhat the request does.
variablestableNoRequest variables of any DNML type.
defaultstableNoConnection values for all operations.
executiontableNoRun options for the full request.
dynamodb, athenaoperation blocksNoOperation blocks only.
xtableNoExtension data. See Unknown keys.

All keys use camelCase. Do not use the reserved key operations.

Defaults and Execution

[defaults] sets connection values for all operations. An operation that sets the same key uses its own value. Defaults can use templates.

KeyApplies to
profileNameAll operations.
regionAll operations.
endpointUrlAll operations. See Endpoints.
workgroupAthena operations.
outputLocationAthena queries.

[execution] holds run options for the full request:

KeyDefaultPurpose
onError"continue"The default error policy.
timeoutMsNoneThe request deadline, in milliseconds.
allowDestructivefalseShows that the request has destructive operations.
[defaults]
profileName = "${AWS_PROFILE}"
region = "ap-southeast-2"
workgroup = "analytics"

[execution]
onError = "continue"
timeoutMs = 120000

In the app, these keys are in Request settings.

Operation Blocks

Each operation is a [[<namespace>.<operation>]] block. The namespaces are dynamodb and athena.

[[dynamodb.query]]
name = "Find recent order"
tableArn = "arn:aws:dynamodb:ap-southeast-2:111122223333:table/Orders"
keyConditionExpression = "accountId = :accountId"

# Attaches to the most recent [[dynamodb.query]] block
[dynamodb.query.expressionAttributeValues]
":accountId" = "account#42"

[[athena.query]]
name = "Refund report"
region = "ap-southeast-2"
sql = "SELECT * FROM refunds"

[[dynamodb.update]]
name = "Mark reviewed"
dependsOn = "Find recent order"
# ...
  • The header gives the type. There is no type key. An unsupported type causes DNML_UNSUPPORTED_OPERATION before any operation runs.
  • Blocks keep their file order, also between different types.
  • A sub-table, such as [dynamodb.query.expressionAttributeValues], belongs to the last [[dynamodb.query]] block above it.
  • dependsOn can move a dependency before the operations that need it. See Ordering.

The operation types:

Naming Rules

Request Names

  • It must be the same as the filename without .dnml, and it must not be empty.
  • It must not contain / \ : * ? " < > | or control characters.
  • It must not start or end with whitespace, or end with ..
  • It must not be collection, in any letter case.

When you rename a request in the app, Dynomate renames the file.

Operation Names

  • Each operation must have a unique name.
  • Dynomate compares normalized names. A normalized name is lowercase, and each group of whitespace becomes one underscore. Find recent order becomes find_recent_order. Two equal normalized names cause DNML_DUPLICATE_OPERATION.
  • Templates read a result by the normalized name. This works only if that name has only lowercase letters, digits and underscores, and no digit at the start.

Variable Names

  • It must start with a letter or underscore, then letters, digits or underscores.
  • It must not be the same as a normalized operation name. This causes DNML_ROOT_COLLISION.

Collection Marker

collection.dnml marks a folder as a collection. It has no operation blocks.

# Collection marker (collection.dnml). One of these per collection directory.
version = "1.0"
type = "dynomate-collection"
created = 2026-09-05T00:00:00Z

[metadata]
description = "Order service runbooks"
author = "Platform team"

[metadata.tags]
service = "orders"
KeyRequiredPurpose
versionYes"1.0".
typeYesAlways "dynomate-collection".
createdYesA TOML date-time or an RFC 3339 string.
metadata.descriptionNoFree text.
metadata.authorNoFree text.
metadata.tagsNoA table of string labels.

The app writes the marker when you make a collection.

Unknown Keys

A key that DNML does not define causes DNML_UNKNOWN_KEY, at the top level and in operation blocks.

The app opens the request and shows these keys under Unrecognized fields of the request or the operation. Remove them before you save or run the request.

Extensions

Extension keys keep your own data. They never cause errors. Dynomate keeps them when it saves, but does not use them when the request runs:

  • Keys that start with x-, at the top level or in an operation block.
  • The top-level [x] table.
version = "1.0"
name = "nightly-cleanup"
x-owner = "platform-team"

[x]
ticket = "OPS-142"

[[dynamodb.scan]]
name = "Find expired sessions"
x-note = "Runs after the TTL sweep"
# ...

An extension cannot add an operation type. [[x.something]] is not an operation block.

Canonical Serialization

Dynomate saves a request in one canonical layout. The same request always gives the same bytes, so a diff shows only real changes.

PartLayout
Fileversion, name, description, top-level x- keys, [variables], [defaults], [execution], [x]. Then the operation blocks, with a blank line between them.
Blockname, description, dependsOn, enabled, onError, timeoutMs, profileName, region, endpointUrl, tableArn, operation keys, then tags.
Free-form mapsSub-tables with sorted keys, for example variables, item, keyValues and expressionAttributeValues.
Small fixed mapsOne-line inline tables, for example guard and partitionKey.
Lists of mapsOne element on each line and a trailing comma, for example puts, keys and actions.
Keys without a valueNot written.
StringsDouble quotes. SQL and expressions on many lines use '''.
Line ends\n, with one newline at the end of the file.
[[dynamodb.batchWrite]]
name = "Seed orders"
tableArn = "arn:aws:dynamodb:ap-southeast-2:111122223333:table/Orders"
puts = [
  { accountId = "account#42", orderId = "order-1", status = "NEW" },
  { accountId = "account#42", orderId = "order-2", status = "NEW" },
]

You do not have to write this layout. Dynomate reads all valid TOML.

Common Keys

Each operation accepts these keys. The Operation reference gives the other keys.

name string Required
The display name of the operation. It must be unique in the request, and other operations use it to refer to the operation. In the app: Rename dialog › Operation name
description string
Free-text notes about the operation. In the app: Description and tags dialog › Description
dependsOn string or string[]
The names of the operations that must succeed before this operation runs. One name is the same as a list with one name. In the app: Operation header › Add dependency
enabled boolean
If false, Dynomate skips the operation and all operations that depend on it. The default is true. In the app: Operation actions menu › Enable / Disable
onError enum: "stop" | "continue" | "ignore"
What Dynomate does when the operation fails: "stop" stops the request, "continue" skips only its dependents, and "ignore" lets dependents run without its result. The default is the request setting. In the app: Execution tab › On operation error
timeoutMs integer
The maximum time for the operation, in milliseconds. It replaces the default timeout of the operation, but the request timeout still applies. In the app: Execution tab › Operation timeout (ms)
tags string[]
Your own labels for the operation. They are not AWS resource tags. In the app: Description and tags dialog › Tags
profileName string
The AWS profile that Dynomate uses to connect. If you omit it, Dynomate uses the request default, then the profile named "default". In the app: Operation header › AWS profile
region string
The AWS region, required for Athena operations, List tables and PartiQL statements. If the operation also has a tableArn, the two regions must match. In the app: Operation header › Region
endpointUrl string
A custom endpoint, for example DynamoDB Local. It must use HTTPS, or HTTP on localhost or a loopback address. An endpoint in the file needs confirmation or approval before the request runs. In the app: no field. Dynomate keeps the key when it saves the request.
tableArn string
The full ARN of the table, which gives its name and region. All DynamoDB operations except List tables and PartiQL statements require it. In the app: Operation header › Table ARN

name, dependsOn, enabled, onError and timeoutMs cannot use templates.