Academy
⌘K
Getting Started
  • Platform Overview
  • AWS Marketplace Setup
  • Quickstart Guide
Connections
  • Overview
Workflow Builder
  • Overview
  • Nodes Catalog
Helix AI Assistant
  • Overview
Mapping Engine
  • Overview
Workflow Library
  • Overview
  • HL7
  • FHIR
  • Insurance
  • Agentic
  • Mapping
Security & Infrastructure
  • Architecture
  • HIPAA Compliance
  • Performance & Scalability
← Back to ConnectHealth
Get Started
Back to Nodes
AWS1 input → 2 outputs

AWS Athena Query

payload.queryP… (object)payload.queryS… (string)payload.database (string)payload.workgr… (string)AWSAWS Athena QueryOutput 1payload.rows (array)payload.columns (array)payload.count (number)Output 2payload.success (boolean)payload.error (string)payload.errorT… (string)Data flowProperty

Runs a SQL query against an AWS Athena workgroup/database (tables registered in the Glue Data Catalog), replacing the discontinued-by-AWS S3 Select approach. Credentials come from the shared ec-aws-config node rather than a dedicated per-node config node.

Configuration

AWS Config
Reference to the shared ec-aws-config node that holds the region and credentials (IAM role or access keys). Required.
Database
The Glue Data Catalog database the query resolves unqualified table names against — it becomes Athena's QueryExecutionContext.Database. Leave it blank only when every table in the SQL is written fully qualified as database.table. A query that references an unqualified table with no Database set fails on Output 2 with errorType: "Query Failed". Overridable per message via msg.payload.database.
Data Catalog
The data catalog that contains the database — Athena's QueryExecutionContext.Catalog. Almost always left empty, which means AwsDataCatalog, the account's built-in Glue catalog for this region. Set an explicit name only if you have registered an additional catalog (a Hive metastore, or an Athena federated-query connector such as a JDBC or DynamoDB source) and want to query through it. An unknown catalog name fails on Output 2 with errorType: "Query Failed" or "Not Found". Not overridable per message.
Workgroup
The Athena workgroup the query runs in. A workgroup is Athena's unit of isolation and governance: it carries the default query-result S3 location, the per-query and per-workgroup data-scan limits, result-encryption settings, the CloudWatch metrics namespace, and the cost tag the scan is billed under. primary is the default workgroup every account has. If the chosen workgroup has "Override client-side settings" enabled, its own result location and encryption win over whatever this node sends. Overridable per message via msg.payload.workgroup.
Output Location
An s3://bucket/prefix/ URI. Athena always writes the raw result set (plus a .metadata file) to S3 first; this node then reads it back via GetQueryResults. This field sets ResultConfiguration.OutputLocation on StartQueryExecution. It is required unless the selected workgroup already defines a default result location — and a workgroup that enforces its settings ignores this value entirely. The credentials on the AWS Config node need s3:PutObject and s3:GetObject (and usually s3:GetBucketLocation) on that path. With no location at all, Athena rejects the request up front and Output 2 carries errorType: "Invalid Request"; a location the credentials can't write to fails the running query, so Output 2 carries errorType: "Query Failed". Overridable per message via msg.payload.outputLocation.
Max Rows
Caps how many rows this node reads back from the result set (default 1000); on hitting the cap it stops paging and sets payload.truncated: true. It does not limit what Athena scans or bills — use a LIMIT in the SQL for that.

Writing the query

The SQL Query field is a syntax-highlighting editor. Full Presto/Trino SQL is supported — joins, sub-queries, GROUP BY, aggregates. The Examples dropdown loads a starter query you can adapt.

Parameterised queries

Author the query once with tokens and let the per-run values arrive on msg.payload.queryParams. There are two token forms:

  • {{name}} — a bound value. It is sent to Athena as a positional bind parameter (? / ExecutionParameters) and never spliced into the SQL text, so an upstream (or end-user-influenced) value in a value position cannot change the query. Use it everywhere a literal would go — right of =, inside LIKE, IN, BETWEEN, … — and write it without surrounding quotes: WHERE state = {{st}}, not = '{{st}}'.
  • {{= name}} — a raw identifier (table or column name). Athena cannot bind identifiers, so this token is substituted into the text — and is therefore checked against a strict allowlist (letters, digits, underscore; dot-qualified allowed). Anything else routes to Output 2 (errorType: "Invalid Identifier") before Athena runs.
Configured query:
    SELECT * FROM {{= tbl}}
    WHERE state = {{st}} AND age > CAST({{minAge}} AS INTEGER)

msg.payload.queryParams = { tbl: "patients", st: "TX", minAge: "18" }
    → SELECT * FROM patients WHERE state = ? AND age > CAST(? AS INTEGER)
      ExecutionParameters: ["TX", "18"]

Tokens accept nested paths ({{patient.id}}). All bind values are sent to Athena as strings and cast per column context — wrap the token in CAST(… AS <type>) when a non-text comparison needs an explicit type. An empty-string value is rejected up front (Athena will not bind it). Any token with no matching entry in queryParams routes the message to Output 2 (errorType: "Unresolved Placeholders") before Athena is called. Parameterised queries require Athena engine v3.

Inputs

payload.queryParams object
Name → value map. {{name}} tokens become bound parameters; {{= name}} tokens are substituted as identifiers after an allowlist check.
payload.queryString string
Overrides the configured SQL query for this call (tokens in it are still compiled the same way).
payload.database string
Overrides the configured database for this call.
payload.workgroup string
Overrides the configured workgroup for this call.
payload.outputLocation string
Overrides the configured S3 output location for this call.

Output 1 — success

payload.rows array
Matching rows as plain objects keyed by column name.
payload.columns array
Column names, in result order.
payload.count number
Number of rows returned.
payload.truncated boolean
true if the Max Rows cap stopped result fetching before Athena's result set was fully paged through.
payload.stats object
dataScannedBytes / executionTimeMs, as reported by Athena.

Output 2 — error

payload.error / errorType / solution / awsCode
Every failure routes here rather than throwing — unresolved placeholders ("Unresolved Placeholders"), an identifier token that isn't a bare name ("Invalid Identifier"), a rejected request such as a missing output location ("Invalid Request"), a query that ran but failed ("Query Failed"), cancellation, polling timeout ("Query Timeout"), throttling, and bad/insufficient credentials.

IAM requirements

athena:StartQueryExecution, athena:GetQueryExecution, athena:GetQueryResults, s3:GetObject/s3:PutObject on the query result bucket, and glue:GetTable/glue:GetDatabase when querying a Glue Data Catalog table.

Known limitations

  • {{name}} values are bound via Athena ExecutionParameters, which requires Athena engine v3 — on engine v2 a query that carries a value token fails on Output 2. Identifier tokens ({{= name}}) are still substituted textually (Athena cannot bind identifiers) and are allowlist-checked instead.
  • All bind values are passed as strings; Athena casts per column context. A non-text comparison may need CAST(? AS <type>) written into the SQL.
  • Polling for query completion is bounded (default ~60 attempts at 1s) — a very long-running query surfaces as a timeout on Output 2 even though it may still finish in Athena.
  • Max Rows bounds result fetching, not Athena's own scan — use a LIMIT in the query to control scan cost/latency.