This is a question keeps confusing me. Although AppSync is marketed as for GraphQL while API Gateway is for REST. But API Gateway could also work with GraphQL via apollo server in lambda.
So what actually makes one a better option over the other?
It depends on how much control you want over your backend service execution, how much code you feel like writing, and then of course how much you want to pay.
With API Gateway and Lambda you are writing a handler function that executes a full graphql request against your resolver definitions that you write in whatever language your Lambda runtime is set to. You have to consider how much memory your application will need, and what kind of features you want to support. You will also need to do some legwork to get subscriptions working with websockets.
AWS AppSync is more of a managed service, where you register your GraphQL schema with AppSync and the service takes care of things like query validation, batching calls, and of course out-of-the-box subscriptions. In it you only need to define how you want to "map" the GraphQL request using VTL (Velocity Templating Language) to define calls to your downstream data sources ie. specifically DynamoDB, ElasicSearch, HTTP, Aurora Serverless RDS, or Lambda. Keep in mind, the Lambda functions you write for AppSync only have to handle a single resolver, whereas with Apollo Server you are writing all of the resolver logic in your code.
Ultimately whichever way you choose has its pros and cons. With Apollo Server on Lambda you get to control the full HTTP GraphQL request cycle at the expense of additional complexity to do so. With AppSync you have a more "managed" service where you only need to define the resolvers to talk to your data sources (and in many cases, these can be auto-generated for you using Amplify CLI) at the expense of having finer control over the whole GraphQL request.