基于AWS Cognito、AppSync、EventBridge与Flutter Amplify的移动端微服务后端认证及数据同步架构咨询
Hey there, let's break down your AWS architecture questions step by step—this is a super common pattern when building microservices with Cognito, so you're already thinking in the right direction!
First: Confirming Cognito's Unique User ID
Great question about the userId format. Cognito assigns every user a permanent, globally unique identifier called the sub attribute (short for "subject"). This is a GUID-like string (e.g., 12345678-1234-1234-1234-1234567890ab) and it never changes—even if the user updates their username, email, or linked social accounts. This is exactly the identifier you should use as the foreign key across all your microservice DynamoDB tables (Community, Workouts, Performance, etc.) to ensure consistent, unique user mapping.
Second: Bidirectional Sync Between Cognito and Microservice Databases
Let's split this into two flows: Cognito changes triggering updates to your microservices, and microservice changes syncing back to Cognito. We'll use EventBridge for async decoupling and API Gateway/Lambda for sync scenarios where you need immediate consistency.
1. Syncing Cognito Changes to Microservice DynamoDB Tables
Your earlier pain point with Post-Confirmation not firing for social logins is easy to fix with Cognito's native EventBridge integration:
- Enable Cognito EventBridge Integration: In your Cognito User Pool settings, turn on EventBridge integration. This lets Cognito send events like
UserCreated,UserUpdated, andUserDeleteddirectly to EventBridge whenever a user is created (including social logins), updated, or removed. - Route Events to Lambda via EventBridge Rules: Create EventBridge rules that match these Cognito events and forward them to dedicated Lambda functions. For example:
- A
UserCreatedevent triggers a Lambda that initializes user records in your Community (empty friends list), Workouts (default training plan), and Performance (baseline metrics) DynamoDB tables—using thesubas the primary key for each. - A
UserUpdatedevent triggers a Lambda that syncs core attribute changes (like display name or profile photo) to any microservice tables that need that data.
- A
- Why this works better than Post-Confirmation: Social login users trigger
UserCreatedthe moment their account is provisioned in Cognito (even though they're already confirmed), so you don't miss the sync trigger.
2. Syncing Microservice Changes Back to Cognito
For when your microservices need to update core user attributes in Cognito (e.g., a user updates their workout goal in the Workouts service and wants that reflected in their Cognito profile), use these patterns:
- Async Sync (Preferred for Most Cases):
- When your microservice updates its DynamoDB table (e.g., Community service adds a friend), have the service publish an event to EventBridge (e.g.,
UserFriendListUpdatedorUserWorkoutGoalChanged). - Create an EventBridge rule that routes these events to a Lambda function, which calls the Cognito
AdminUpdateUserAttributesAPI to update the corresponding custom attribute in the User Pool. - This keeps your services decoupled—if Cognito is temporarily unavailable, EventBridge will retry the event automatically, and you can set up a dead-letter SQS queue to catch failed events for manual review.
- When your microservice updates its DynamoDB table (e.g., Community service adds a friend), have the service publish an event to EventBridge (e.g.,
- Sync Sync (For Immediate Consistency):
- If you need the Cognito update to happen in real-time (e.g., a user changes their display name and needs it to show up immediately in the app), use API Gateway as a single entry point. Have your Flutter app call an API Gateway endpoint, which triggers a Lambda that:
- Updates the relevant microservice DynamoDB table.
- Calls the Cognito
UpdateUserAttributesAPI (via Amplify or the AWS SDK) to sync the change.
- Add idempotency to the Lambda (using the request ID or user
sub+ attribute key) to avoid duplicate updates if the app retries the request.
- If you need the Cognito update to happen in real-time (e.g., a user changes their display name and needs it to show up immediately in the app), use API Gateway as a single entry point. Have your Flutter app call an API Gateway endpoint, which triggers a Lambda that:
Best Practices to Keep This Clean
- Separate Core vs. Extended Attributes: Only store core user data (email, display name, profile photo, auth-related flags) in Cognito. Keep extended data (friends lists, workout plans, performance metrics) in their respective microservice tables—Cognito has limits on custom attributes, and you don't want to bloat it with non-auth data.
- Use
subEverywhere: Always reference users by their Cognitosubin all your DynamoDB tables. Never use usernames or emails as foreign keys—these can be changed by users, breaking your mappings. - Avoid Dual Writes from Frontend: Ditch the pattern of calling Amplify and AppSync from the Flutter app at the same time. Let your backend handle the sync via EventBridge/Lambda—this keeps your frontend logic simpler and reduces the risk of inconsistent data.
Recap of Your Original Pain Points
- Social Login Sync: Fixed by using Cognito's
UserCreatedEventBridge event instead of Post-Confirmation. - Dual Write Inconsistency: Eliminated by centralizing sync logic in backend services via EventBridge and Lambda, so the frontend only needs to call one API/GraphQL endpoint.
- Unique User ID: Use Cognito's
subattribute—it's a permanent GUID that works for all auth types.
内容的提问来源于stack exchange,提问作者Stradis

