By using AWS re:Post, you agree to the Terms of Use
/Possible to override default GraphQL @model resolvers with Lambda function resolvers?/

Possible to override default GraphQL @model resolvers with Lambda function resolvers?


I'm hoping to leverage a GraphQL model managed by Amplify / AppSync and build on that, using the DynamoDB table for storage but then adding my own custom business logic. In the current example, I want a model that represents a session for an external API, and I want to override the create mutation with a Lambda function that will call the external API to get an access token, and then add that token to the newly-created @model instance.

I'm trying to do that by disabling the default create resolver and then adding my own in my GraphQL schema:

type ExternalAPISession @model(mutations: { create: null }) @auth(rules: [{allow: public}]) {
  id: ID!
  username: String! @index(name: "byUsername", queryField: "getExternalAPISessionByUsername")
  access_token: String!
  refresh_token: String!

type Mutation {
  createExternalAPISession(username: String, password: String): ExternalAPISession @function(name: "CreateExternalAPISession-${env}")

But, even though I tried to disable the default create resolver, I still get this error when I try to amplify push this schema:

⠹ Updating resources in the cloud. This may take a few minutes...

Following resources failed

Resource Name: MutationcreatePaytronixSessionResolver (AWS::AppSync::Resolver)
Event Type: create
Reason: Only one resolver is allowed per field. (Service: AWSAppSync; Status Code: 400; Error Code: BadRequestException; Request ID: 08399b17-1e38-46f6-bf9f-06f68356c21a; Proxy: null)

Is it even possible to do what I'm trying to do? I can't seem to find any explicit confirmation in the documentation that you can override a default CRUD action with your own Lambda function resolver. I see that you can override the default CRUD VTL templates with your own VTL. But can you override them with Lambda functions?

2 Answers
Accepted Answer

I made it go!!

For anyone with a similar problem who lands here after a search, this explains the issue:

MrArnoldPalmer commented on Feb 24, 2021

Hey there, so this is a result of the fix we did for #12635. There seems to be an issue with AppSync in CFN where ordering of delete/create operations causes duplicates to occur when replacing existing resolvers. I created this issue to track that: #13269

Right now they only workaround is to remove the resolver resources, deploy that to the stack, then add them back and redeploy. If you want to avoid downtime, you can spin up a parallel instance of the GraphqlAPI construct in a new stack, point your clients to that, and then remove the old one.

Apparently, the @model(mutations: { create: null }) adjustment to the model, and the new create mutation that I want to add, can't be deployed at the same time. I had to first remove the default resolver and deploy that with the new parameters on the @model. Then I could successfully add the new Lambda functiuon resolver using @function.

I had to comment out the custom mutator that I was trying to overwrite:

// type Mutation {
//  createExternalAPISession(username: String, password: String): ExternalAPISession @function(name: "CreateExternalAPISession-${env}")
// }

I deployed the schema with amplify push, including the @model(mutations: { create: null }). Then un-commented my new mutator and deployed again with another amplify push. Success.

answered a month ago

If you found your way here after searching, then you might also be interested in learning how to locate the DynamoDB table that AppSync created for your @model in your GraphQL schema. Overriding the CRUD operation is one thing, but once you can do that you will still need to access the underlying storage.

If you're faced with that challenge, then please take a look at the "How to pass stack outputs from app resources into function stack parameters" header in another one of my questions that I ended up answering by myself:

answered 22 days ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions