-
Notifications
You must be signed in to change notification settings - Fork 90
Description
Describe the feature you'd like to request
Currently, Amplify API generates all resolvers using VTL (Velocity Template Language). This has a couple drawbacks:
- Niche language: VTL has minimal adoption outside AppSync and legacy Java apps. Most developers have no prior exposure to it.
- Custom AppSync extensions: AppSync adds custom VTL utilities ($util.dynamodb, $util.transform, etc.) not found in standard VTL documentation.
- Poor debugging: VTL errors are cryptic, there's no step-through debugging, and the feedback loop is slow.
- Difficult to extend: Customizing auto-generated resolvers requires learning VTL's quirks—inconsistent null handling, unusual syntax, lack of modern language features.
- Weak tooling: Minimal IDE support, no autocomplete, no type checking.
- Hard to test: Unit testing VTL in isolation is non-trivial compared to JavaScript.
AppSync now officially supports APPSYNC_JS as a first-class runtime. JavaScript is nearly universal among web/mobile developers, has excellent tooling, and resolvers can be tested with standard tools like Jest.
Describe the solution you'd like
Update the GraphQL transformer to generate APPSYNC_JS resolvers instead of VTL. This should be the new default for all generated resolvers including: pipeline resolvers, unit resolvers, and custom business logic.
Example of the improvement:
VTL (current):
#set($modelQueryExpression.expression = "#typeName = :typeName")
#set($modelQueryExpression.expressionNames = { "#typeName": "__typename" })
#set($modelQueryExpression.expressionValues = {
":typeName": $util.dynamodb.toDynamoDB($ctx.args.typeName)
})
#if(!$util.isNull($ctx.args.sortDirection) && $ctx.args.sortDirection == "DESC")
#set($modelQueryExpression.scanIndexForward = false)
#else
#set($modelQueryExpression.scanIndexForward = true)
#endAPPSYNC_JS (proposed):
import { util } from '@aws-appsync/utils';
export function request(ctx) {
const { typeName, sortDirection } = ctx.args;
return {
operation: 'Query',
query: {
expression: '#typeName = :typeName',
expressionNames: { '#typeName': '__typename' },
expressionValues: util.dynamodb.toMapValues({ ':typeName': typeName }),
},
scanIndexForward: sortDirection !== 'DESC',
};
}Describe alternatives you've considered
-
Keep VTL as an option: Could offer both runtimes, but this adds maintenance burden and fragments the community/documentation. Better to move forward with JS.
-
Manual rewrite: Eject resolvers and rewrite in JS manually, but this breaks the Amplify workflow and requires maintaining resolvers outside the Amplify lifecycle.
-
Custom transformers: Build custom GraphQL transformers that output JS, but this duplicates significant work that Amplify should handle natively.
-
Continue with VTL: Invest time mastering VTL, but this knowledge has limited transferability outside AppSync and the syntax remains error-prone.
Additional context
- APPSYNC_JS is the modern choice: AWS added APPSYNC_JS as a first-class runtime specifically because VTL was a pain point. AWS Docs
We now primarily support the APPSYNC_JS runtime and its documentation. Please consider using the APPSYNC_JS runtime and its guides here.
- JavaScript is universal: Nearly every Amplify user already knows JS/TS. VTL requires learning a niche language with minimal transferable value.
- TypeScript support: APPSYNC_JS supports TypeScript for type-safe resolver development with compile-time checks.
- Testability: JS resolvers can be unit tested with standard tools using the @aws-appsync/utils package.
- Linting available: @aws-appsync/eslint-plugin provides linting for JS resolvers.
- Reduce maintenance burden: Maintaining one runtime (JS) is simpler than supporting both VTL and JS long-term.
- Community alignment: VTL is consistently cited as a major friction point in Amplify API development. Migrating to JS removes a significant barrier to adoption and customization.
Is this something that you'd be interested in working on?
- 👋 I may be able to implement this feature request
Would this feature include a breaking change?
-
⚠️ This feature might incur a breaking change