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
| Key | Type | Required | Purpose |
|---|---|---|---|
version | string | Yes | "1.0", or "1.1" for a request with an Amazon Aurora DSQL operation. See Versioning. |
name | string | Yes | The same as the filename. See Naming rules. |
description | string | No | What the request does. |
variables | table | No | Request variables of any DNML type. |
defaults | table | No | Connection values for all operations. |
execution | table | No | Run options for the full request. |
dynamodb, athena, dsql | operation blocks | No | Operation blocks only. |
x | table | No | Extension 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.
| Key | Applies to |
|---|---|
profileName | All operations. |
region | All operations. For Aurora DSQL, it must match the AWS Region in clusterArn. |
endpointUrl | DynamoDB and Athena operations. See Endpoints. |
workgroup | Athena operations. |
outputLocation | Athena queries. |
clusterArn | Aurora DSQL operations. |
databaseRole | Aurora DSQL operations. |
Aurora DSQL operations take only profileName, region, clusterArn and databaseRole from [defaults]. See Aurora DSQL connection keys.
[execution] holds run options for the full request:
| Key | Default | Purpose |
|---|---|---|
onError | "continue" | The default error policy. |
timeoutMs | None | The request deadline, in milliseconds. |
allowDestructive | false | Shows 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, athena and dsql. The dsql namespace, for Aurora DSQL operations, is available from DNML 1.1.
[[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
typekey. An unsupported type causesDNML_UNSUPPORTED_OPERATIONbefore 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. dependsOncan 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 orderbecomesfind_recent_order. Two equal normalized names causeDNML_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.dnml # 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" | Key | Required | Purpose |
|---|---|---|
version | Yes | "1.0". |
type | Yes | Always "dynomate-collection". |
created | Yes | A TOML date-time or an RFC 3339 string. |
metadata.description | No | Free text. |
metadata.author | No | Free text. |
metadata.tags | No | A 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.
| Part | Layout |
|---|---|
| File | version, name, description, top-level x- keys, [variables], [defaults], [execution], [x]. Then the operation blocks, with a blank line between them. |
| Block | name, description, dependsOn, enabled, onError, timeoutMs, profileName, region, endpointUrl, tableArn, operation keys, then tags. Aurora DSQL operations have clusterArn and databaseRole after region. |
| Free-form maps | Sub-tables with sorted keys, for example variables, item, keyValues and expressionAttributeValues. |
| Small fixed maps | One-line inline tables, for example guard and partitionKey. |
| Lists of maps | One element on each line and a trailing comma, for example puts, keys, actions and statements. |
| Keys without a value | Not written. |
| Strings | Double 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, with two exceptions. tableArn is only for DynamoDB operations other than List tables. Aurora DSQL operations do not accept endpointUrl. 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. For Aurora DSQL query and DSQL transaction, the app has no field for this key. Edit the file. 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. For Aurora DSQL query and DSQL transaction, the app has no field for this key. Edit the file. In the app: Execution tab › Operation timeout (ms)
- 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. For Aurora DSQL operations, it is optional and must match the Region in clusterArn. The app has no Region field for Aurora DSQL operations. 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. Aurora DSQL operations do not accept it. 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.