AppSync subscriptions: waiting for start_ack can still result in missing events

It seems like that when AppSync returns a `start_ack` message in response to a subscription `start` it won't necessarily mean that all future events will be delivered.

Subscriptions are the mechanism to deliver real-time events from AppSync. It is based on WebSockets and its protocol is documented [here](https://docs.aws.amazon.com/appsync/latest/devguide/real-time-websocket-client.html).

In the protocol, a client needs to send a `start` message with the GraphQL query to start receiving updates. Then AppSync responds with a `start_ack` if everything is OK and then sends `data` events whenever an update happens.

Reading the documentation my impression was that `start_ack` is the moment when the subscription is live and all future events will be delivered. But what I'm seeing is that **it's not the case**. Even when the event is strictly triggered after the `start_ack` is received sometimes it is not delivered to the client.

Why is it a problem?

A common pattern for APIs with real-time updates is to subscribe to updates first then query the current state. This way there is no "temporal dead zone" when updates are lost. But that requires a definitive *point in time* when the subscription is live. Without that, it's only best-effort and messages will be lost every now and then especially in cases when the subscription is made just before the event, common in tests and some async workflows.

Real-time updates, especially in AppSync, is a complex topic and it's easy to get wrong. I've [written about it before](https://advancedweb.hu/shorts/apollos-subscribetomore-is-the-wrong-abstraction/), it has a [separate section in my book](https://www.graphql-on-aws-appsync-book.com/client-side/implementing-subscriptions/), and I even [made a library](https://github.com/sashee/appsync-subscription-observable) because I wasn't particularly happy with the AWS-provided one.

I noticed tests using subscriptions timeouting for a long time now, but i wrote it off as "something complex is happening" and added some retries to handle it. A message is published to IoT Core that triggers a Lambda, that writes to DynamoDB then it triggers the subscription. A lot can go wrong so it's realistic that the 10-ish seconds sometimes pass.

But I then started working on a simpler setup and still noticed that some events seemingly never arrive. This time I could pinpoint the issue because if a parallel subscription is opened before then the event is delivered there. So the problem must be that the subscription is not live even though AppSync says it is.

Hopefully, it will get fixed soon.

Bug report opened [in the AppSync repo](https://github.com/aws/aws-appsync-community/issues/405).

#aws #appsync

Originally published [on my blog](https://advancedweb.hu/shorts/appsync-subscriptions-waiting-for-start_ack-can-still-result-in-missing-events/)

Building a real-time WebSocket client in AWS AppSync - AWS AppSync GraphQL

AWS AppSync real-time WebSocket client setup

AppSync Event API を使用したリアルタイム文字起こしをブラウザに表示させてみた!
https://qiita.com/hirota_kodai/items/9b2c846d8c7b4bc7bc95?utm_campaign=popular_items&utm_medium=feed&utm_source=popular_items

#qiita #lambda #Kinesis #AmazonConnect #AppSync

AppSync Event API を使用したリアルタイム文字起こしをブラウザに表示させてみた! - Qiita

こんにちは。株式会社ウフルの廣田です。 この記事は「2025 Japan AWS Jr. Champions 夏のQiitaリレー」の14日目です。 過去の投稿(リンク集)はこちらからご覧ください! 1. はじめに AWS AppSyncとは サーバーレスで高性...

Qiita

GraphQL tip: Have the subscription types contain all filterable fields on the top-level.

For example, a Todo event that should allow filtering by user, group, severity, and id, should have these as well as the item itself:

```graphql
type TodoEvent {
userId: ID!
groupId: ID!
todoId: ID!
severity: Severity!
todo: Todo
}
```

Originally, it was the only way for filtering in AppSync, but that changed when it [started supporting filters on nested fields](https://docs.aws.amazon.com/appsync/latest/devguide/aws-appsync-real-time-enhanced-filtering.html#aws-appsync-real-time-enhanced-filters-nested-schema-fields.title). So, why it's still a best practice?

The primary reason is deletion: this structure makes it easy to support sending an event when the item is deleted and all the filters will work.

Then an additional benefit is when there is a filter that is not present in the entity itself. For example, if a Todo item's `userId` can be changed it is useful to notify the original owner. In that case, a `prevUserId` field can be added to the subscription allowing users to subscribe to events when an item is removed from them.

#graphql #tips #appsync

Originally published [on my blog](https://advancedweb.hu/shorts/graphql-tip-have-the-subscription-types-contain-all-filterable-fields-on-the-top-level/)

Defining enhanced subscriptions filters in AWS AppSync - AWS AppSync GraphQL

Learn about enhanced subscription filtering in AWS AppSync.

GraphQL tip: Only make fields required if they are present for all users

In GraphQL it's possible to mark a field as required with the `!`. For example, a `User` always have a `Project` according to this schema:

```graphql
type User {
name: String!
email: String!
project: Project!
}
```

Marking fields required is a powerful tool in the GraphQL toolbox as clients won't need handle the case when the field is null. But it can also lead to a cascading null effect.

For example, let's say the Project has a `client` field that also can't be null:

```graphql
type User {
name: String!
email: String!
project: Project!
tickets: [Ticket!]!
}

type Project {
name: String!
description: String!
client: String!
}

// + Ticket
```

Let's say the `Project.client` is considered sensitive information and will be removed for non-admin users.

Then a query that gets the `User`, its `Project`, and and then the `client` field will fail to return any data:

```graphql
query {
user(id: "user1") {
name
email
project {
name
description
client
}
tickets: {
id
}
}
}
```

The result:

```json
{
"data": null,
"errors": ...
}
```

Because of this, be mindful which fields you mark as required. If a field can be null for some users during normal operations, such as when you have different access levels, it should be optional. A field should be marked as mandatory only when it returns a value in every case.

#appsync #graphql

Originally published [on my blog](https://advancedweb.hu/shorts/graphql-tip-only-make-fields-required-if-they-are-present-for-all-users/)

GraphQL tip: Only make fields required if they are present for all users

AppSync footgun: util.error does not work if called with non-string arguments

The `util.error` function terminates the current resolver with the error provided in the argument, similar to how an exception would work. Its signature is:

```
util.error(String, String?, Object?, Object?)
```

But what happens when the provided arguments don't match this signature?

Consider this code:

```js
if (ctx.result.statusCode < 200 || ctx.result.statusCode >= 300) {
util.error(ctx.result.statusCode);
}
return JSON.parse(ctx.result.body);
```

The expectation here is that if the `statusCode` is outside the 2xx range then it will result in an error.

But what happens instead is that the `util.error` is silently ignored. There is no error, no warning, it behaves as it was never called.

All these lines are no-ops:

```js
util.error(25);
util.error(true);
util.error("abc", 25);
```

Issue opened at [https://github.com/aws/aws-appsync-community/issues/384](https://github.com/aws/aws-appsync-community/issues/384).

#aws #appsync

Originally published [on my blog](https://advancedweb.hu/shorts/appsync-footgun-util-error-does-not-work-if-called-with-non-string-arguments/)

AWS初心者がAppSyncを使ってみた - Qiita

はじめに昨年、ANGEL Dojo 2024に参加し、3か月間でサービスの企画から開発までを行う経験をしました。私たちのチームは、電話練習アプリ「Tele Talk Tutor(T3)」を開発し…

Qiita

In case anyone is interested, after discussing the AWS product roadmap with them, it is clear that DataStore is on the way out. Recommend that no one use it for any new development and anyone currently using it begin making plans to rearchitect. #Amplify #AppSync

There does not seem to be any first party offline-first for mobile data sync service in AWS anymore. Looking into third party services next.

Anyone used #Amplify #AppSync with DataStore in their iOS app? I’d love to ask a few noob questions if you wouldn’t mind.

New AWS::AppSync::ChannelNamespace

Use the AWS::AppSync::ChannelNamespace resource to creates a channel namespace associated with an Api.
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsyc-channelnamespace.html #appsync #cloudformation

AWS CloudFormation