AppSync GraphQL APIs should have field-level logging enabled
Field-level logging in AppSync captures resolver execution details, including request mappings, response mappings, and errors at the individual field level. Without it, you lose visibility into which resolvers are failing, how long they take, and what data they return. This makes debugging production issues slow and leaves you blind to data exfiltration patterns or injection attempts against your GraphQL API.
AppSync APIs often sit in front of multiple data sources (DynamoDB, Lambda, RDS) and act as an aggregation layer. A single GraphQL query can fan out to dozens of resolvers. Logging at the API level alone won't tell you which resolver misbehaved. Field-level logs sent to CloudWatch give you the granularity needed for both operational troubleshooting and security investigations.
Retrofit consideration
Setting field_log_level to ALL on a high-traffic API can generate substantial CloudWatch Logs volume. Estimate log costs before switching from NONE to ALL on production APIs; ERROR satisfies the control at a fraction of the ingestion cost.
Implementation
Choose the approach that matches how you manage Terraform.
Use the compliance.tf module to enforce this control by default. See get started with compliance.tf.
module "appsync" {
source = "pcidss.compliance.tf/terraform-aws-modules/appsync/aws"
version = ">=3.0.0"
authentication_type = "AWS_IAM"
log_field_log_level = "ERROR"
logging_enabled = true
name = "pofix-abc123"
schema = "type Query { hello: String }"
}
module "appsync" {
source = "nistcsf.compliance.tf/terraform-aws-modules/appsync/aws"
version = ">=3.0.0"
authentication_type = "AWS_IAM"
log_field_log_level = "ERROR"
logging_enabled = true
name = "pofix-abc123"
schema = "type Query { hello: String }"
}
module "appsync" {
source = "acscessentialeight.compliance.tf/terraform-aws-modules/appsync/aws"
version = ">=3.0.0"
authentication_type = "AWS_IAM"
log_field_log_level = "ERROR"
logging_enabled = true
name = "pofix-abc123"
schema = "type Query { hello: String }"
}
If you use terraform-aws-modules/appsync/aws, set the right module inputs for this control. You can later migrate to the compliance.tf module with minimal changes because it is compatible by design.
module "appsync" {
source = "terraform-aws-modules/appsync/aws"
version = ">=3.0.0"
authentication_type = "AWS_IAM"
log_field_log_level = "ERROR"
logging_enabled = true
name = "pofix-abc123"
schema = "type Query { hello: String }"
}
Use AWS provider resources directly. See docs for the resources involved: aws_appsync_graphql_api.
resource "aws_appsync_graphql_api" "this" {
authentication_type = "AWS_IAM"
log_config {
cloudwatch_logs_role_arn = "arn:aws:iam::123456789012:role/example-role"
field_log_level = "ERROR"
}
name = "pofix-abc123"
}
What this control checks
The aws_appsync_graphql_api resource passes when its log_config block sets field_log_level to "ERROR" or "ALL". It fails when field_log_level is "NONE" or the log_config block is absent entirely. log_config also requires a cloudwatch_logs_role_arn pointing to an IAM role with permissions to write to CloudWatch Logs: a trust policy allowing appsync.amazonaws.com to assume the role, and an attached policy granting logs:CreateLogGroup, logs:CreateLogStream, and logs:PutLogEvents. Without that role, the API cannot deliver logs even if the log level is set correctly.
Common pitfalls
Missing or underprivileged CloudWatch IAM role
AppSync silently fails to write logs when
cloudwatch_logs_role_arnis missing or the referenced role lacks write permissions, even though the control may still report a pass based onfield_log_levelalone. Create an IAM role that trustsappsync.amazonaws.comand grantslogs:CreateLogGroup,logs:CreateLogStream, andlogs:PutLogEvents. Without it, your configuration passes the check but produces no logs.Confusing field_log_level with request-level logging
The
log_configblock has bothfield_log_levelandexclude_verbose_content. Flippingexclude_verbose_contentto true reduces log detail but has no effect on the control result. What the policy evaluates isfield_log_level; settingcloudwatch_logs_role_arnwithout also settingfield_log_levelto a non-NONE value still fails.High log volume with ALL on busy APIs
Use
"ERROR"rather than"ALL"on high-throughput APIs."ALL"logs every resolver invocation, including successful ones, and on an API processing thousands of queries per second that adds up to gigabytes of CloudWatch Logs per day."ERROR"satisfies the control at a fraction of the cost; the tradeoff is losing trace data for requests that succeed.Terraform apply fails when IAM role and API are created together
If the IAM role and the AppSync API are created in the same
terraform apply, the apply can fail because the role ARN isn't resolved when thelog_configblock is evaluated. Reference the role'sarnattribute directly incloudwatch_logs_role_arnrather than constructing the ARN string manually; that reference establishes the dependency implicitly. Adddepends_ononly if the direct attribute reference isn't sufficient.
Audit evidence
Config rule evaluation results showing each AppSync API as compliant, or Security Hub findings with PASSED status for this control, are the primary audit artifacts. Supporting those, the associated CloudWatch Logs log group should contain recent field-level log entries, confirming that logging is actively functioning and not just configured.
The AppSync API settings page in the AWS Console shows the current logging configuration, including the field resolver log level and the associated IAM role ARN. CLI output from aws appsync get-graphql-api --api-id <id> showing fieldLogLevel as ERROR or ALL in the logConfig object provides direct proof.
Framework-specific interpretation
PCI DSS v4.0: Requirement 10 calls for audit trails on all access to system components and cardholder data. For AppSync APIs that process or proxy cardholder data, resolver-level logging is what gives you that trail at the granularity examiners expect.
NIST Cybersecurity Framework v2.0: DE.CM and DE.AE both require continuous monitoring of system components for anomalies. Field-level resolver logs give you the error patterns and request details needed to actually do that for anything going through your GraphQL API.
Related controls
Tool mappings
Use these identifiers to cross-reference this control across tools, reports, and evidence.
Compliance.tf Control:
appsync_graphql_api_field_level_logging_enabledAWS Config Managed Rule:
APPSYNC_LOGGING_ENABLEDCheckov Checks:
CKV_AWS_193,CKV_AWS_194Powerpipe Control:
aws_compliance.control.appsync_graphql_api_field_level_logging_enabledProwler Check:
appsync_field_level_logging_enabledAWS Security Hub Control:
AppSync.2
Last reviewed: 2026-03-08