Dual AWS provider: @pulumi/aws + @pulumi/aws-native
Reventless's AWS adapters use two Pulumi AWS providers in the same deployment:
| Provider | Used for | Why |
|---|---|---|
@pulumi/aws (classic) | Everything by default — DynamoDB, Lambda, SQS, SNS, S3, IAM, AppSync API/DataSource/Function, etc. | Mature, Terraform-bridged, broad coverage. The Pulumi-recommended primary provider. |
@pulumi/aws-native (Cloud Control) | Narrowly: appsync.Resolver only. | Cloud Control's CFN handler waits server-side for schema → resolver propagation, eliminating a known race that surfaces as NotFoundException: No field named X. |
This matches Pulumi's official guidance: use @pulumi/aws as the
backbone; reach for @pulumi/aws-native only when a specific resource
benefits from Cloud Control semantics.
The AppSync resolver creation race
When Reventless deploys an AppSync GraphQL API, it pushes the SDL via
StartSchemaCreation (AWS SDK) and creates one resolver per top-level
Query field. With the classic @pulumi/aws provider, resolver creation
occasionally raced ahead of schema-field propagation inside AppSync's
control plane and failed with:
NotFoundException: No field named X found on type Query
Resolvers are created via @pulumi/aws-native (Cloud Control API).
Cloud Control hands the request to the AWS::AppSync::Resolver
CloudFormation handler, which waits server-side for the field to be
visible before reporting success.
Empirical validation: 25 deploys (5× eu-west-1 + 5× us-east-1, each
up + destroy) of a smoke-test stack succeeded with zero post-ACTIVE
sleep between schema push and resolver creation.
Where the line is drawn
- Bindings — both providers have ReScript bindings in
rescript-pulumi-aws. Classic bindings live insrc/AppSync/,src/DynamoDb/, etc. The native binding sits undersrc/AwsNative/AppSync/and is exposed asPulumiAws.AwsNative.AppSync.Resolver. - Adapter —
AppSync_Resolver_Native.respreserves the call shape of the classicResolvermodule (makeUnitJsResolver,makePipelineJsResolver) so call sites are agnostic to the underlying provider. - Wiring —
QueryDbResolvers_AppSync.resshadowsResolverwith the native adapter:open PulumiAws.AppSync // Function, DataSource, GraphQLApi
module Resolver = AppSync_Resolver_Native - AppSync
Functionstays on classic. Functions don't reference schema field names at create time, so they don't hit the propagation race. Pipeline resolvers extractfunctionIdoutputs from classic Functions and pass them into the nativepipelineConfig.functionsarray — Pulumi supports crossing provider boundaries this way.
What to do if the race resurfaces
-
Confirm the symptom.
NotFoundException: No field named Xin the Pulumi update log under anaws-native:appsync:Resolverresource. -
Identify the field. The resource name in the Pulumi log is the resolver's
name(e.g.MyReadModelByIdResolver). The failing GraphQL field is in the error message itself. -
Short-term workaround — reinstate a sleep. Add a fixed wait after
StartSchemaCreationreachesACTIVEinAppSync_Adapter.resinsidewaitForSchemaActive(e.g. 15 ssetTimeoutin theACTIVE/SUCCESSbranch). Redeploy. -
File an issue. Open a ticket against
pulumi-aws-nativewith the stack trace and Pulumi version. The whole point of using Cloud Control here is that the CFN handler waits internally; if it stops doing so, that's an upstream regression worth reporting. -
Fall back if needed. If the upstream regression persists, the alternative is a custom Pulumi dynamic resource that wraps
@aws-sdk/client-appsyncdirectly with retry-on-NotFoundExceptionclassifier (exn.name === "NotFoundException"ANDexn.messagecontains"No field named") and exponential backoff (2 s → 4 s → 8 s → 16 s → 32 s, capped ~3 min). Pulumi dynamic resources accept aliases, so it can adopt existing native resolvers without forcing another replace cycle.
When to extend the native surface
Add a new aws-native binding only when:
- The classic resource has a known, reproducible problem (race, slow eventual consistency, missing feature).
- The Cloud Control / CFN handler demonstrably solves it (verify with a smoke test in two regions).
- The slowdown is acceptable (Cloud Control adds ~5–15 s per resource).
Otherwise default to @pulumi/aws.