AWS Amplify Hosting for ML/AI Services Guide / ML Services Integration Guide
Part 2 of 2
AWS Amplify Hosting for ML/AI Services Guide
Part 2 of 2

AWS Amplify ML Services Integration Guide

Designing, Developing, Integrating and Deploying
Amplify Hosting for SPAs with Corporate ML Services Access

Enterprise-Grade Integration

This comprehensive guide provides detailed instructions for implementing secure, scalable AWS Amplify applications with integrated machine learning services including SageMaker and Bedrock, featuring enterprise authentication through Azure Entra ID and Lambda processors through Regional API Gateway integration with private backend connectivity options.

Security First

Multi-layer security with JWT validation, WAF protection, and compliance frameworks

Production Ready

Complete implementation with CI/CD pipelines and Infrastructure as Code

ML Integration

Seamless integration with SageMaker and Bedrock for AI-powered applications

Reference implementation status: The architecture and examples are remediated design patterns. Validate current service quotas, CDK and SDK versions, tenant-specific SAML claims, model entitlements, and all deployment outputs before production use.

Version 2.4.1 | Remediated: July 2026

Target Audience: Enterprise Developers, DevOps Engineers, Solution Architects

Table of Contents

1. Introduction and Overview
1.1 Purpose and Scope
1.2 Target Audience
1.3 Prerequisites
1.4 Architecture Benefits
2. Architecture Overview
2.1 High-Level Architecture
2.2 Component Descriptions
2.3 Architecture Layers
3. Authentication and Authorization
3.1 Authentication Flow
3.2 JWT Token Validation
3.3 Authorization Patterns
4. Data Flow Architecture
4.1 End-to-End Data Flow
4.2 SageMaker Integration
4.3 Bedrock Integration
5. Security Architecture
5.1 Multi-Layer Security Model
5.2 JWT Token Security
5.3 Data Protection and Compliance
6. Implementation Guide
6.1 Environment Setup
6.2 Cognito Configuration
6.3 API Gateway Setup
6.4 Lambda Implementation
6.5 Amplify Configuration
7. Deployment Guide
7.1 Infrastructure as Code
7.2 CI/CD Pipeline Setup
7.3 Environment Promotion
8. Best Practices and Considerations
8.1 Security Best Practices
8.2 Performance Optimization
8.3 Monitoring and Alerting
9. Troubleshooting and Monitoring
9.1 Common Issues and Solutions
9.2 Monitoring Setup
10. Appendix
10.1 Reference Links
10.2 Glossary
10.3 Version History

1. Introduction and Overview

1.1 Purpose and Scope

This guide provides comprehensive instructions for designing, developing, integrating, and deploying AWS Amplify hosting solutions for Single Page Applications (SPAs), specifically Angular applications, with secure access to corporate machine learning services including Amazon SageMaker and Amazon Bedrock.

The integration architecture emphasizes enterprise-grade security through Azure Entra ID authentication via Amazon Cognito, Regional API Gateway configurations with AWS WAF protection, and Lambda-based processors for ML service orchestration.

1.2 Target Audience

  • Enterprise Developers: Frontend and backend developers implementing Angular SPAs with AWS ML services
  • DevOps Engineers: Infrastructure specialists managing CI/CD pipelines and deployment automation
  • Solution Architects: Technical architects designing secure, scalable ML-enabled applications
  • Security Engineers: Professionals implementing enterprise authentication and authorization patterns

1.3 Prerequisites

Technical Prerequisites

  • AWS Account with appropriate permissions for Amplify, Cognito, API Gateway, Lambda, SageMaker, and Bedrock
  • Azure Entra ID (formerly Azure AD) tenant with administrative access
  • Node.js 18+ and npm/yarn package manager
  • Angular CLI 16+ and TypeScript knowledge
  • AWS CLI configured with appropriate credentials
  • Git version control system

Knowledge Prerequisites

  • Intermediate Angular development experience
  • Understanding of OAuth 2.0 and OpenID Connect protocols
  • Basic knowledge of AWS services and IAM concepts
  • Familiarity with RESTful API design and implementation
  • Understanding of JWT tokens and authentication flows

1.4 Architecture Benefits

Security Benefits

  • • Multi-layer authentication and authorization
  • • Native Cognito/JWT validation; custom authorizers only for documented additional policy logic
  • • WAF protection against common attacks
  • • Regional API Gateway with WAF and controlled backend connectivity
  • • Can support applicable SOC 2, GDPR, and HIPAA requirements when paired with required contractual, technical, privacy, governance, and evidence controls

Performance Benefits

  • • CloudFront CDN for global content delivery
  • • Lambda@Edge for edge computing capabilities
  • • Optimized ML model inference through SageMaker
  • • Efficient token caching and validation
  • • Auto-scaling Lambda processors

Scalability Benefits

  • • Serverless architecture with automatic scaling
  • • Elastic ML model endpoints
  • • Distributed authentication through Cognito
  • • API Gateway throttling and rate limiting
  • • Multi-region deployment capabilities

Operational Benefits

  • • Infrastructure as Code with CDK/CloudFormation
  • • Automated CI/CD pipelines
  • • Comprehensive monitoring and alerting
  • • Cost optimization through serverless pricing
  • • Simplified maintenance and updates

2. Architecture Overview

2.1 High-Level Architecture

Overall System Architecture

User Browser Angular SPA Amplify Hosting Managed hosting + CDN Amazon Cognito Managed login + federation Entra ID Corporate SAML IdP AWS WAF Managed rules + rate limits Regional REST API Native Cognito authorizer Lambda Bounded orchestration Async Orchestration SQS / Step Functions SageMaker AI Approved endpoint allowlist Bedrock Approved model profiles 1 2a 2b 3 4 5 6 7 8a 8b 9
Sequence legend
  1. 1: Amplify Hosting’s managed hosting and CDN service delivers the SPA to the user browser.
  2. 2a: Amazon Cognito returns a redirect response to the user browser to initiate federated authentication.
  3. 2b: The user browser follows that redirect to Entra ID for corporate authentication.
  4. 3: Entra ID returns the SAML response to Amazon Cognito.
  5. 4: Amazon Cognito completes the authorization-code flow with PKCE and returns Cognito tokens to the SPA loaded in the user browser.
  6. 5: The SPA sends the Cognito access token in the Authorization: Bearer header to the public Regional API path.
  7. 6: AWS WAF evaluates the API request before API Gateway processing.
  8. 7: API Gateway performs native Cognito token validation and invokes the bounded Lambda integration.
  9. 8a: Bounded synchronous requests invoke only approved Bedrock models or inference profiles.
  10. 8b: Bounded synchronous requests invoke only approved SageMaker endpoints.
  11. 9: Long-running jobs are submitted to asynchronous orchestration rather than held open behind API Gateway.

Figure 1: Remediated overall system architecture. AWS-managed ML services remain outside any customer-VPC boundary; interface endpoints may be added when private service access is required.

Amplify CloudFront Integration Architecture

User Browser
Angular SPA
HTTPS Requests
CloudFront
CDN + Edge Locations
Caching & Distribution
Amplify Hosting
Managed hosting + build pipeline
Static Asset Serving

Regional API Gateway Security Path

AWS WAF Managed rules and rate limits Regional API Gateway Validation, throttling, and routing Cognito Authorizer Native access-token validation Lambda Processor Approved-resource orchestration 1 2 3
Sequence legend
  1. 1: AWS WAF evaluates the public API request against managed rules and rate-limiting controls before the request proceeds to the Regional API Gateway.
  2. 2: Regional API Gateway applies method configuration, request validation, throttling, and routing, then invokes the native Cognito authorizer for access-token validation.
  3. 3: Only an authorized request is forwarded to the Lambda processor for approved-resource orchestration.

Boundary note: Private APIs require private client connectivity and an execute-api VPC endpoint; they are not directly callable by a public browser.

2.2 Component Descriptions

Component Purpose Key Features Integration Points
Angular SPA Frontend application Responsive UI, Authentication, ML Service Calls Cognito, API Gateway
AWS Amplify Hosting & CI/CD Auto-deployment, SSL, Custom Domains Managed CDN, Git repository, custom domain
CloudFront Content Delivery Global CDN, Edge Caching, SSL Termination Amplify, Lambda@Edge
Cognito Authentication User Pools, Identity Pools, SAML/OIDC Azure Entra ID, API Gateway
API Gateway API Management Regional endpoint, throttling, monitoring Lambda, WAF, VPC
Cognito Authorizer Authorization JWT Validation, Policy Generation, Caching Cognito, API Gateway
Lambda Processors Business Logic ML Orchestration, Data Processing, Response Formatting SageMaker, Bedrock, DynamoDB
SageMaker ML Inference Custom Models, Real-time Endpoints, Batch Processing Lambda, S3, ECR
Bedrock Foundation Models LLMs, Text Generation, Embeddings Lambda, S3, CloudWatch

2.3 Architecture Layers

Frontend Layer

Angular SPA hosted on AWS Amplify with CloudFront distribution

  • • Responsive design with Angular Material
  • • Authentication integration with Cognito
  • • HTTP interceptors for token management
  • • Error handling and user feedback

Authentication Layer

Cognito User Pools with Azure Entra ID federation

  • • SAML 2.0 integration with Azure Entra ID
  • • JWT token generation and validation
  • • User groups and role-based access control
  • • Multi-factor authentication support

API Layer

Regional API Gateway with WAF protection and native Cognito authorization

  • • Regional endpoint for the public SPA; private backend connectivity where required
  • • Request/response validation and transformation
  • • Rate limiting and throttling policies
  • • Comprehensive logging and monitoring

ML Services Layer

SageMaker and Bedrock integration through Lambda processors

  • • Real-time model inference endpoints
  • • Foundation model access through Bedrock
  • • Asynchronous processing capabilities
  • • Model versioning and A/B testing support

3. Authentication and Authorization

3.1 Authentication Flow

Cognito–Entra Authentication and API Authorization Flow

Angular SPA Browser client Amazon Cognito Managed login + token endpoint Microsoft Entra ID SAML identity provider Regional API Gateway Public API path Native Cognito User-pool authorizer Lambda Processor Authorized request only 1 2a 2b 3 4 5 6 7
Sequence legend
  1. 1: The SPA starts the Cognito authorization-code flow with PKCE, state, and nonce.
  2. 2a: Amazon Cognito returns a redirect response to the user browser to initiate federated authentication.
  3. 2b: The user browser follows that redirect to Microsoft Entra ID for SAML authentication.
  4. 3: Microsoft Entra ID returns the SAML response to Amazon Cognito.
  5. 4: Amazon Cognito completes the authorization-code flow with PKCE and returns Cognito tokens to the SPA in the browser.
  6. 5: The SPA sends the Cognito access token in the Authorization: Bearer header to the public Regional API path.
  7. 6: API Gateway applies the native Cognito user-pool authorizer to validate the access token.
  8. 7: Only an authorized request is forwarded to the Lambda processor.

3.2 JWT Token Validation Process

JWT Token Validation Process

Token Structure Validation
Header.Payload.Signature verification
Signature Verification
RS256 with Cognito public keys
Claims Validation
iss, exp, iat, token_use, and client_id/scope validation
Application Authorization
Mapped enterprise role, tenant, operation, and resource
Native API Authorization
Cognito authorizer validates the access token
Context Enrichment
User metadata for downstream services

Security Note: Native and Custom Authorization

Use the native Cognito authorizer for standard access-token validation. If a custom authorizer is introduced for tenant, resource, or risk decisions, design its cache key, policy scope, token-expiry handling, and revocation latency together; disable caching when a safe reusable policy cannot be produced.

3.3 Authorization Patterns

Authorization Pattern Use Case Implementation Security Level
Role-Based Access Control (RBAC) Standard user permissions Mapped Entra app role + application policy enforcement Medium
Attribute-Based Access Control (ABAC) Dynamic permissions Mapped claims + policy engine/context evaluation High
Resource-Based Authorization Data-specific access Resource policy or policy engine with authoritative ownership data High
Time-Based Access Scheduled operations Policy engine evaluates current time, task state, and credential/session expiry Medium

4. Data Flow Architecture

4.1 End-to-End Data Flow

Execution-mode rule: Keep synchronous API requests within an explicit end-to-end budget. Submit long-running inference to SQS, EventBridge, or Step Functions and return a job identifier; use a status endpoint, WebSocket, or event callback for completion. Add idempotency and bounded retries to prevent duplicate inference charges.

Complete Data Flow Architecture

User Input
Angular Form
Authentication
JWT Token
API Gateway
Request Validation
Authorization
Native Cognito Authorizer
Lambda Processor
Business Logic
ML Service
SageMaker/Bedrock
Response Processing
Data Formatting
Angular SPA
UI Update & User Feedback

4.2 SageMaker Integration Flow

SageMaker Integration Flow

1. Data Preprocessing Lambda → Data Validation & Transformation
2. Model Endpoint Invocation Lambda → SageMaker Real-time Endpoint
3. Inference Processing SageMaker → Model Prediction
4. Result Postprocessing Lambda → Response Formatting

Lambda Function Configuration for SageMaker

Configure your Lambda function with appropriate timeout and memory allocation based on your model's requirements. Critical: For synchronous API Gateway integrations, API Gateway enforces a hard 29-second integration timeout, regardless of the Lambda timeout setting. Long-running inference jobs must use an asynchronous pattern (SQS + polling, WebSocket, or Step Functions).

  • • Memory: 128MB – 10,240MB (10 GB)
  • • Timeout (sync via API Gateway): Maximum effective timeout is 28 seconds — API Gateway hard limit is 29s
  • • Timeout (async invocation via SQS/EventBridge): Up to 15 minutes (900 seconds)
  • • For inference >28s: Use async pattern — return a Job ID immediately and poll for results
  • • Concurrent executions: Configure based on SageMaker endpoint capacity
  • • Error handling: Implement retry logic with exponential backoff

4.3 Bedrock Integration Flow

Bedrock Integration Flow

1. Prompt Engineering Lambda → Prompt Template Processing
2. Foundation Model Invocation Lambda → Bedrock Runtime API
3. Model Processing Bedrock → Foundation Model Inference
4. Response Parsing Lambda → Content Extraction & Formatting

Bedrock Use Cases

Text Generation
  • • Content creation and summarization
  • • Code generation and documentation
  • • Email and report writing
Conversational AI
  • • Chatbots and virtual assistants
  • • Customer support automation
  • • Interactive Q&A systems
Text Analysis
  • • Sentiment analysis and classification
  • • Entity extraction and recognition
  • • Language translation
Embeddings
  • • Semantic search and similarity
  • • Recommendation systems
  • • Document clustering

5. Security Architecture

5.1 Multi-Layer Security Model

Defense in Depth Security Architecture

Layer 1: Edge Security - CloudFront + WAF + DDoS Protection
Layer 2: Network Security - VPC + Private Subnets + Security Groups
Layer 3: API Security - Private API Gateway + Request Validation
Layer 4: Authentication - Cognito + Azure Entra ID + MFA
Layer 5: Authorization - Native Cognito token validation plus application-level RBAC/ABAC and resource policy
Layer 6: Application Security - Lambda Functions + IAM Roles + Encryption
Layer 7: Data Security - Encryption at Rest + In Transit + Key Management

5.2 JWT Token Security Implementation

Token Structure

Header: Algorithm (RS256), Token Type (JWT)
Payload: User Claims, Groups, Permissions, Expiration
Signature: RS256 with Cognito signing key

Security Features

• Short expiration times (1-24 hours)
• Refresh token rotation
• Audience validation
• Issuer verification
• Signature validation with public keys

5.3 Data Protection and Compliance

Encryption Strategy

Data in Transit

  • • TLS 1.2 minimum for all HTTPS connections (TLS 1.3 negotiated where supported)
  • • CloudFront Security Policy: TLSv1.2_2021 recommended
  • • Certificate pinning in mobile apps
  • • API Gateway SSL termination
  • • VPC endpoint encryption

Data at Rest

  • • S3 bucket encryption with KMS
  • • DynamoDB encryption at rest
  • • Lambda environment variable encryption
  • • CloudWatch Logs encryption

Compliance Framework Support

SOC 2 Type II

  • • Security controls documentation
  • • Availability monitoring
  • • Processing integrity validation
  • • Confidentiality measures

GDPR Compliance

  • • Data minimization principles
  • • Right to erasure implementation
  • • Consent management
  • • Data portability features

HIPAA (Healthcare)

  • • PHI encryption and access controls
  • • Audit logging and monitoring
  • • Business Associate Agreements
  • • Risk assessment procedures

PCI DSS (Payments)

  • • Secure network architecture
  • • Cardholder data protection
  • • Vulnerability management
  • • Regular security testing

Audit and Monitoring

CloudTrail Logging

  • • API call logging
  • • User activity tracking
  • • Resource access monitoring

CloudWatch Monitoring

  • • Real-time metrics
  • • Custom dashboards
  • • Automated alerting

Security Hub

  • • Centralized findings
  • • Compliance status
  • • Security standards

6Implementation Guide

Code validation statusAll snippets in this guide were re-audited in July 2026. Python, JSON, YAML, and shell syntax were locally validated. TypeScript/CDK snippets were normalized against current AWS CDK v2 and Amplify v6 APIs; compile and deploy them against the exact dependency versions in the project lock files and replace all documented placeholders.

6.1 Environment Setup Prerequisites

Before writing any application code, set up the full toolchain. Complete all four steps below in order.

  1. Install Node.js 18 LTSRequired runtime for Angular CLI, AWS CDK, and all JavaScript tooling.
  2. Install global CLIsAngular CLI, AWS CLI v2, and AWS CDK must all be available on your $PATH.
  3. Configure AWS credentialsRun aws configure with an IAM user or role that has permissions for Cognito, API Gateway, Lambda, Amplify, and Bedrock.
  4. Install project dependenciesRun npm ci inside both frontend/ and infrastructure/.
sh
scripts/bootstrap.sh
# 1 — Node.js 22 LTS (Debian/Ubuntu)
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt-get update
sudo apt-get install -y nodejs unzip

# 2 — AWS CLI v2
curl -fsSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o awscliv2.zip
unzip -q awscliv2.zip
sudo ./aws/install --update
rm -rf aws awscliv2.zip

# 3 — Authenticate for local development with short-lived SSO credentials
aws configure sso
aws sso login

# 4 — Install project dependencies from lock files
(cd frontend       && npm ci)
(cd infrastructure && npm ci)

# 5 — Run CLIs from the project dependencies; avoid unpinned global versions
(cd frontend       && npx ng version)
(cd infrastructure && npx cdk --version)

Project Directory Structure

amplify-ml-app/ ├── frontend/ # Angular SPA │ └── src/ │ ├── app/ │ │ ├── auth/ # Auth module + service + interceptor │ │ ├── ml-services/ # ML API service + components │ │ └── shared/ # Shared utilities, error interceptor │ └── environments/ # Dev + prod environment configs ├── infrastructure/ # AWS CDK stacks │ └── lib/ │ ├── cognito-construct.ts │ ├── api-construct.ts │ └── main-stack.ts ├── lambda/ │ ├── ml-policy/ # Entitlement and resource policy helpers │ └── ml-processor/ # Bedrock / SageMaker calls (Python) └── amplify.yml # Amplify Hosting build spec (frontend only)

Environment Files — Dev vs Production

Each environment must receive the complete Cognito managed-login domain emitted by infrastructure. Do not derive it from the user-pool ID, and do not configure an identity pool unless the SPA actually requires AWS credentials.

Development
// src/environments/environment.ts
export const environment = {
  production: false,
  cognito: {
    userPoolId: 'us-east-1_XXXXXXXXX',
    userPoolWebClientId: 'XXXXXXXXXXXXXXXXXX',
    domain: 'my-company-ml-app-dev.auth.us-east-1.amazoncognito.com',
    region: 'us-east-1',
    apiScope: 'ml-api/invoke',
  },
  api: {
    baseUrl: 'https://api.example.com/dev',
    region: 'us-east-1',
  },
} as const;
Production
// src/environments/environment.prod.ts
export const environment = {
  production: true,
  cognito: {
    userPoolId: 'us-east-1_YYYYYYYYY',
    userPoolWebClientId: 'YYYYYYYYYYYYYYYYYY',
    domain: 'my-company-ml-app.auth.us-east-1.amazoncognito.com',
    region: 'us-east-1',
    apiScope: 'ml-api/invoke',
  },
  api: {
    baseUrl: 'https://api.example.com/prod',
    region: 'us-east-1',
  },
} as const;

6.2 Cognito and Entra Federation CDK

This remediated construct creates the user pool, Entra SAML provider, managed-login domain, and an app client that explicitly supports the Entra provider. Production uses retention and deletion protection. Authorization entitlements must be mapped explicitly from Entra application roles or another governed source; creating Cognito groups alone does not populate federated users.

Required Entra configuration Configure the enterprise application with Cognito’s SAML entity ID and ACS URL, issue stable application-role claims, and test sign-in and sign-out. Do not rely on broad Entra group claims without handling group overage and token-size limits.
TS
infrastructure/lib/cognito-construct.ts
import * as cdk from 'aws-cdk-lib';
import * as cognito from 'aws-cdk-lib/aws-cognito';
import { Construct } from 'constructs';

export interface CognitoConstructProps {
  readonly domainPrefix: string;
  readonly callbackUrls: string[];
  readonly logoutUrls: string[];
}

export class CognitoConstruct extends Construct {
  readonly userPool: cognito.UserPool;
  readonly userPoolClient: cognito.UserPoolClient;
  readonly domainPrefix: string;
  readonly apiScope = 'ml-api/invoke';

  constructor(scope: Construct, id: string, props: CognitoConstructProps) {
    super(scope, id);

    this.userPool = new cognito.UserPool(this, 'UserPool', {
      selfSignUpEnabled: false,
      signInAliases: { email: true },
      removalPolicy: cdk.RemovalPolicy.RETAIN,
      deletionProtection: true,
      accountRecovery: cognito.AccountRecovery.EMAIL_ONLY,
      mfa: cognito.Mfa.OFF, // Enforce corporate MFA in Entra for federated-only users.
      customAttributes: {
        enterpriseRole: new cognito.StringAttribute({ mutable: true, maxLen: 256 }),
        tenantId: new cognito.StringAttribute({ mutable: true, maxLen: 64 }),
      },
    });

    const entra = new cognito.UserPoolIdentityProviderSaml(this, 'EntraID', {
      userPool: this.userPool,
      name: 'EntraID',
      metadata: cognito.UserPoolIdentityProviderSamlMetadata.url(
        'https://login.microsoftonline.com/<tenant-id>/federationmetadata/2007-06/federationmetadata.xml'
      ),
      attributeMapping: {
        email: cognito.ProviderAttribute.other(
          'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress'
        ),
        givenName: cognito.ProviderAttribute.other(
          'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname'
        ),
        familyName: cognito.ProviderAttribute.other(
          'http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname'
        ),
        custom: {
          enterpriseRole: cognito.ProviderAttribute.other(
            'http://schemas.microsoft.com/ws/2008/06/identity/claims/role'
          ),
          tenantId: cognito.ProviderAttribute.other(
            'http://schemas.microsoft.com/identity/claims/tenantid'
          ),
        },
      },
    });

    const invokeScope = new cognito.ResourceServerScope({
      scopeName: 'invoke',
      scopeDescription: 'Invoke approved ML operations',
    });
    const resourceServer = this.userPool.addResourceServer('MlApiResourceServer', {
      identifier: 'ml-api',
      scopes: [invokeScope],
    });

    this.domainPrefix = props.domainPrefix;
    this.userPool.addDomain('ManagedLoginDomain', {
      cognitoDomain: { domainPrefix: props.domainPrefix },
    });

    this.userPoolClient = this.userPool.addClient('SpaClient', {
      generateSecret: false,
      supportedIdentityProviders: [
        cognito.UserPoolClientIdentityProvider.custom('EntraID'),
      ],
      oAuth: {
        flows: { authorizationCodeGrant: true },
        scopes: [
          cognito.OAuthScope.OPENID,
          cognito.OAuthScope.EMAIL,
          cognito.OAuthScope.PROFILE,
          cognito.OAuthScope.resourceServer(resourceServer, invokeScope),
        ],
        callbackUrls: props.callbackUrls,
        logoutUrls: props.logoutUrls,
      },
      readAttributes: new cognito.ClientAttributes()
        .withStandardAttributes({ email: true, givenName: true, familyName: true })
        .withCustomAttributes('enterpriseRole', 'tenantId'),
      writeAttributes: new cognito.ClientAttributes()
        .withStandardAttributes({ email: true, givenName: true, familyName: true })
        .withCustomAttributes('enterpriseRole', 'tenantId'),
      accessTokenValidity: cdk.Duration.minutes(60),
      idTokenValidity: cdk.Duration.minutes(60),
      refreshTokenValidity: cdk.Duration.days(1),
      enableTokenRevocation: true,
      preventUserExistenceErrors: true,
    });

    this.userPoolClient.node.addDependency(entra);
  }
}
Entitlement mapping Map the Entra application-role claim to an application entitlement in a pre-token-generation trigger or authorization service. Validate the mapped entitlement at the API/resource layer. Cognito groups are not automatically synchronized from Entra.

6.3 Regional API Gateway Setup CDK

The public browser path uses a Regional REST API. AWS WAF protects the stage, and a native Cognito user-pool authorizer validates access tokens before Lambda invocation. A private REST API is a separate pattern that requires private client connectivity and an API Gateway interface VPC endpoint.

TS
infrastructure/lib/api-construct.ts
import * as cdk from 'aws-cdk-lib';
import * as apigateway from 'aws-cdk-lib/aws-apigateway';
import * as cognito from 'aws-cdk-lib/aws-cognito';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as logs from 'aws-cdk-lib/aws-logs';
import * as wafv2 from 'aws-cdk-lib/aws-wafv2';
import { Construct } from 'constructs';

export interface ApiConstructProps {
  readonly userPool: cognito.UserPool;
  readonly processor: lambda.Function;
  readonly allowedOrigin: string;
  readonly authorizationScope: string;
}

export class ApiConstruct extends Construct {
  readonly api: apigateway.RestApi;

  constructor(scope: Construct, id: string, props: ApiConstructProps) {
    super(scope, id);

    const accessLogs = new logs.LogGroup(this, 'AccessLogs', {
      retention: logs.RetentionDays.THIRTY_DAYS,
      removalPolicy: cdk.RemovalPolicy.RETAIN,
    });

    this.api = new apigateway.RestApi(this, 'Api', {
      restApiName: 'ML App API',
      endpointConfiguration: { types: [apigateway.EndpointType.REGIONAL] },
      defaultCorsPreflightOptions: {
        allowOrigins: [props.allowedOrigin],
        allowMethods: ['POST', 'OPTIONS'],
        allowHeaders: ['Content-Type', 'Authorization'],
      },
      deployOptions: {
        stageName: 'prod',
        dataTraceEnabled: false,
        metricsEnabled: true,
        loggingLevel: apigateway.MethodLoggingLevel.ERROR,
        accessLogDestination: new apigateway.LogGroupLogDestination(accessLogs),
        accessLogFormat: apigateway.AccessLogFormat.jsonWithStandardFields(),
      },
    });

    const authorizer = new apigateway.CognitoUserPoolsAuthorizer(
      this,
      'CognitoAuthorizer',
      { cognitoUserPools: [props.userPool] }
    );

    const integration = new apigateway.LambdaIntegration(props.processor, {
      timeout: cdk.Duration.seconds(25),
    });

    const methodOptions: apigateway.MethodOptions = {
      authorizer,
      authorizationType: apigateway.AuthorizationType.COGNITO,
      authorizationScopes: [props.authorizationScope],
    };

    const ml = this.api.root.addResource('ml');
    ml.addResource('sagemaker').addMethod('POST', integration, methodOptions);
    ml.addResource('bedrock').addMethod('POST', integration, methodOptions);

    const webAcl = new wafv2.CfnWebACL(this, 'ApiWebAcl', {
      defaultAction: { allow: {} },
      scope: 'REGIONAL',
      visibilityConfig: {
        cloudWatchMetricsEnabled: true,
        metricName: 'MlApiWebAcl',
        sampledRequestsEnabled: true,
      },
      rules: [
        {
          name: 'AWSManagedCommonRules',
          priority: 0,
          overrideAction: { none: {} },
          statement: {
            managedRuleGroupStatement: {
              vendorName: 'AWS',
              name: 'AWSManagedRulesCommonRuleSet',
            },
          },
          visibilityConfig: {
            cloudWatchMetricsEnabled: true,
            metricName: 'CommonRules',
            sampledRequestsEnabled: true,
          },
        },
        {
          name: 'RateLimit',
          priority: 1,
          action: { block: {} },
          statement: { rateBasedStatement: { aggregateKeyType: 'IP', limit: 2000 } },
          visibilityConfig: {
            cloudWatchMetricsEnabled: true,
            metricName: 'RateLimit',
            sampledRequestsEnabled: true,
          },
        },
      ],
    });

    const association = new wafv2.CfnWebACLAssociation(this, 'ApiWebAclAssociation', {
      resourceArn: cdk.Stack.of(this).formatArn({
        service: 'apigateway',
        resource: 'restapis',
        resourceName: `${this.api.restApiId}/stages/${this.api.deploymentStage.stageName}`,
        arnFormat: cdk.ArnFormat.SLASH_RESOURCE_NAME,
      }),
      webAclArn: webAcl.attrArn,
    });
    association.node.addDependency(this.api.deploymentStage);
  }
}
Custom authorization Use a Lambda or external policy engine only when the request requires additional resource, tenant, or risk decisions. Do not recreate standard Cognito signature validation in custom code. If a cached TOKEN authorizer is used, never return a policy scoped only to the current methodArn unless caching is disabled.

6.4 Authorization and Entitlement Enforcement Application policy

Authentication proves that Cognito issued a valid access token. The Lambda processor must still enforce application entitlements, tenant boundaries, approved operation types, and server-side resource allowlists. Never trust a client-supplied SageMaker endpoint name or Bedrock model identifier directly.

PY
lambda/ml-processor/authorization.py
from collections.abc import Mapping
from typing import Any

APPROVED_OPERATIONS = {
    'summarize': {'service': 'bedrock', 'resource_key': 'SUMMARY_MODEL_ARN'},
    'classify': {'service': 'sagemaker', 'resource_key': 'CLASSIFIER_ENDPOINT_NAME'},
}
REQUIRED_SCOPE = 'ml-api/invoke'


def authorize_request(
    claims: Mapping[str, Any],
    body: Mapping[str, Any],
    env: Mapping[str, str],
) -> dict[str, str]:
    scopes = set(str(claims.get('scope', '')).split())
    if REQUIRED_SCOPE not in scopes:
        raise PermissionError('required OAuth scope is missing')

    operation = str(body.get('operation', ''))
    mapping = APPROVED_OPERATIONS.get(operation)
    if mapping is None:
        raise PermissionError('operation is not approved')

    resource = env.get(mapping['resource_key'])
    if not resource:
        raise RuntimeError(f"missing configuration: {mapping['resource_key']}")

    return {
        'service': mapping['service'],
        'resource': resource,
        'subject': str(claims.get('sub', '')),
    }
🚫
Fail closed Reject missing or unknown entitlements, operations, tenants, resources, and model profiles. Apply payload limits, content controls, idempotency keys, cost quotas, and audit correlation before invoking an ML service.

6.5 Amplify App Configuration Angular + Amplify v6

Amplify v6 breaking change — Auth API is now modular The legacy import { Auth } from 'aws-amplify' class no longer exists in v6. All auth functions must be imported individually from 'aws-amplify/auth'. The Amplify.configure() structure changed too. Supply the full Cognito managed-login domain emitted by infrastructure rather than deriving it from the user-pool ID.

app.module.ts — Amplify v6 bootstrap

TS
frontend/src/app/app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import {
  HttpClientModule,
  HTTP_INTERCEPTORS,
} from '@angular/common/http';
import { ReactiveFormsModule } from '@angular/forms';
import { Amplify } from 'aws-amplify';
import { environment } from '../environments/environment';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { AuthModule } from './auth/auth.module';
import { MLServicesModule } from './ml-services/ml-services.module';
import { AuthInterceptor } from './auth/auth.interceptor';
import { ErrorInterceptor } from './shared/error.interceptor';

Amplify.configure({
  Auth: {
    Cognito: {
      userPoolId: environment.cognito.userPoolId,
      userPoolClientId: environment.cognito.userPoolWebClientId,
      loginWith: {
        oauth: {
          domain: environment.cognito.domain,
          scopes: ['email', 'openid', 'profile', environment.cognito.apiScope],
          redirectSignIn: [`${window.location.origin}/auth/callback`],
          redirectSignOut: [`${window.location.origin}/auth/logout`],
          responseType: 'code',
        },
      },
    },
  },
});

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    HttpClientModule,
    ReactiveFormsModule,
    AppRoutingModule,
    AuthModule,
    MLServicesModule,
  ],
  providers: [
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true },
    { provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true },
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

auth.service.ts — Amplify v6 named function imports

TS
frontend/src/app/auth/auth.service.ts
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
import {
  fetchAuthSession,
  getCurrentUser,
  signInWithRedirect,
  signOut as amplifySignOut,
} from 'aws-amplify/auth';

export interface User {
  username: string;
  email: string;
  enterpriseRole: string;
  userId: string;
}

@Injectable({ providedIn: 'root' })
export class AuthService {
  private readonly userSubject = new BehaviorSubject<User | null>(null);
  readonly currentUser$ = this.userSubject.asObservable();

  constructor(private readonly router: Router) {
    void this.initializeAuth();
  }

  private async initializeAuth(): Promise<void> {
    try {
      const { username, userId } = await getCurrentUser();
      const session = await fetchAuthSession();
      const payload = session.tokens?.idToken?.payload;

      this.userSubject.next({
        username,
        userId,
        email: String(payload?.['email'] ?? ''),
        enterpriseRole: String(payload?.['custom:enterpriseRole'] ?? ''),
      });
    } catch {
      this.userSubject.next(null);
    }
  }

  async signInWithSAML(): Promise<void> {
    await signInWithRedirect({ provider: { custom: 'EntraID' } });
  }

  async getAccessToken(): Promise<string> {
    const session = await fetchAuthSession();
    const token = session.tokens?.accessToken?.toString();
    if (!token) {
      throw new Error('No Cognito access token is available');
    }
    return token;
  }

  async signOut(): Promise<void> {
    await amplifySignOut();
    this.userSubject.next(null);
    await this.router.navigate(['/auth/login']);
  }

  isAuthenticated(): boolean {
    return this.userSubject.value !== null;
  }

  hasRole(role: string): boolean {
    return this.userSubject.value?.enterpriseRole === role;
  }
}

ml-api.service.ts — Calling ML endpoints with auth

TS
frontend/src/app/ml-services/ml-api.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, from, map, switchMap } from 'rxjs';
import { AuthService } from '../auth/auth.service';
import { environment } from '../../environments/environment';

export interface ClassifyRequest {
  operation: 'classify';
  inputData: unknown;
  parameters?: Record<string, unknown>;
}

export interface SummarizeRequest {
  operation: 'summarize';
  prompt: string;
  parameters?: Record<string, unknown>;
}

export interface MLResponse {
  success: boolean;
  data?: unknown;
  error?: string;
}

@Injectable({ providedIn: 'root' })
export class MLApiService {
  private readonly base = environment.api.baseUrl.replace(/\/$/, '');

  constructor(
    private readonly http: HttpClient,
    private readonly auth: AuthService,
  ) {}

  private headers$(): Observable<HttpHeaders> {
    return from(this.auth.getAccessToken()).pipe(
      map(token => new HttpHeaders({
        'Content-Type': 'application/json',
        Authorization: `Bearer ${token}`,
      })),
    );
  }

  classify(req: ClassifyRequest): Observable<MLResponse> {
    return this.headers$().pipe(
      switchMap(headers => this.http.post<MLResponse>(
        `${this.base}/ml/sagemaker`,
        req,
        { headers },
      )),
    );
  }

  summarize(req: SummarizeRequest): Observable<MLResponse> {
    return this.headers$().pipe(
      switchMap(headers => this.http.post<MLResponse>(
        `${this.base}/ml/bedrock`,
        req,
        { headers },
      )),
    );
  }
}

7Deployment Guide

7.1 Infrastructure as Code CDK

The MainStack composes reusable CDK constructs for Cognito, Lambda, and API Gateway. It emits three outputs — User Pool ID, Client ID, and API URL — that the deployment script uses to write the frontend environment files automatically.

Deployment order This version uses constructs inside one stack. For independently deployed stacks, instantiate them at the app level and use explicit cross-stack references. Use NestedStack only when nested-stack lifecycle semantics are intended.
TS
infrastructure/lib/main-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import { Construct } from 'constructs';
import { ApiConstruct } from './api-construct';
import { CognitoConstruct } from './cognito-construct';

export interface MainStackProps extends cdk.StackProps {
  readonly environmentName: string;
  readonly applicationOrigin: string;
  readonly cognitoDomainPrefix: string;
}

export class MainStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: MainStackProps) {
    super(scope, id, props);

    const bedrockModelArn = new cdk.CfnParameter(this, 'ApprovedBedrockModelArn', {
      type: 'String',
      description: 'ARN of the approved Bedrock foundation model or inference profile',
    });
    const classifierEndpointName = new cdk.CfnParameter(this, 'ClassifierEndpointName', {
      type: 'String',
      description: 'Name of the approved SageMaker endpoint',
    });

    const identity = new CognitoConstruct(this, 'Identity', {
      domainPrefix: props.cognitoDomainPrefix,
      callbackUrls: [`${props.applicationOrigin}/auth/callback`],
      logoutUrls: [`${props.applicationOrigin}/auth/logout`],
    });

    const processor = new lambda.Function(this, 'MLProcessor', {
      functionName: `MLProcessorFunction-${props.environmentName}`,
      runtime: lambda.Runtime.PYTHON_3_12,
      handler: 'index.lambda_handler',
      code: lambda.Code.fromAsset('lambda/ml-processor'),
      timeout: cdk.Duration.seconds(25),
      memorySize: 2048,
      environment: {
        SUMMARY_MODEL_ARN: bedrockModelArn.valueAsString,
        CLASSIFIER_ENDPOINT_NAME: classifierEndpointName.valueAsString,
      },
    });

    processor.addToRolePolicy(new iam.PolicyStatement({
      actions: ['bedrock:InvokeModel'],
      resources: [bedrockModelArn.valueAsString],
    }));

    processor.addToRolePolicy(new iam.PolicyStatement({
      actions: ['sagemaker:InvokeEndpoint'],
      resources: [cdk.Stack.of(this).formatArn({
        service: 'sagemaker',
        resource: 'endpoint',
        resourceName: classifierEndpointName.valueAsString,
      })],
    }));

    const api = new ApiConstruct(this, 'Api', {
      userPool: identity.userPool,
      processor,
      allowedOrigin: props.applicationOrigin,
      authorizationScope: identity.apiScope,
    });

    new cdk.CfnOutput(this, 'UserPoolId', {
      value: identity.userPool.userPoolId,
    });
    new cdk.CfnOutput(this, 'UserPoolClientId', {
      value: identity.userPoolClient.userPoolClientId,
    });
    new cdk.CfnOutput(this, 'CognitoDomain', {
      value: `${identity.domainPrefix}.auth.${this.region}.amazoncognito.com`,
    });
    new cdk.CfnOutput(this, 'CognitoApiScope', {
      value: identity.apiScope,
    });
    new cdk.CfnOutput(this, 'ApiGatewayUrl', {
      value: api.api.url,
    });
  }
}
TS
infrastructure/bin/infrastructure.ts
#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { MainStack } from '../lib/main-stack';

const app = new cdk.App();
const environmentName = String(
  app.node.tryGetContext('environment') ?? process.env.ENVIRONMENT ?? 'dev'
).toLowerCase();

const suffix: Record<string, string> = {
  dev: 'Dev',
  staging: 'Staging',
  prod: 'Prod',
};
if (!(environmentName in suffix)) {
  throw new Error('environment must be dev, staging, or prod');
}

const region = process.env.CDK_DEFAULT_REGION ?? 'us-east-1';
const account = process.env.CDK_DEFAULT_ACCOUNT;
const applicationOrigin = String(
  app.node.tryGetContext('applicationOrigin') ?? 'https://your-domain.example'
);
const cognitoDomainPrefix = String(
  app.node.tryGetContext('cognitoDomainPrefix') ??
  `ml-app-${environmentName}-${account ?? 'local'}-${region}`
).toLowerCase();

new MainStack(app, `MLAppStack-${suffix[environmentName]}`, {
  environmentName,
  applicationOrigin,
  cognitoDomainPrefix,
  env: { account, region },
  tags: {
    Project: 'ML-App',
    Environment: environmentName,
  },
});

7.2 CI/CD Pipeline Setup GitHub Actions

Three jobs run in sequence: testdeploy-infrastructuredeploy-frontend. CDK infrastructure runs in a dedicated GitHub Actions job — never inside Amplify Hosting.

amplify.yml is for the frontend build only Never place cdk deploy inside the Amplify build spec. The Amplify build role has minimal IAM permissions by design. All CDK deployments must run from a GitHub Actions runner (or AWS CodePipeline) that assumes a role with the required permissions.

amplify.yml — Frontend-only build spec

yml
amplify.yml
version: 1
applications:
  - appRoot: frontend
    frontend:
      phases:
        preBuild:
          commands:
            - npm ci
        build:
          commands:
            - npm run build:prod
      artifacts:
        # Angular's current application builder normally emits browser assets here.
        # Confirm the project/outputPath values in angular.json.
        baseDirectory: dist/ml-app/browser
        files:
          - '**/*'
      cache:
        paths:
          - node_modules/**/*

deploy.yml — GitHub Actions full pipeline

yml
.github/workflows/deploy.yml
name: Deploy ML App

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

permissions:
  contents: read
  id-token: write

env:
  AWS_REGION: us-east-1
  NODE_VERSION: '22'

jobs:
  test:
    runs-on: ubuntu-latest
    env:
      CDK_DEFAULT_ACCOUNT: '111111111111'
      CDK_DEFAULT_REGION: us-east-1
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm
          cache-dependency-path: |
            frontend/package-lock.json
            infrastructure/package-lock.json
      - run: cd frontend && npm ci && npm run lint && npm run test:ci && npm run build:prod
      - run: cd infrastructure && npm ci && npm run build && npx cdk synth MLAppStack-Prod -c environment=prod

  deploy-infrastructure:
    needs: test
    if: github.event_name == 'push' && github.ref == 'refs/heads/main'
    environment: production
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ vars.AWS_DEPLOY_ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}
          role-session-name: github-ml-app-${{ github.run_id }}
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ env.NODE_VERSION }}
          cache: npm
          cache-dependency-path: infrastructure/package-lock.json
      - run: cd infrastructure && npm ci && npm run build
      - name: Deploy CDK stack
        run: |
          cd infrastructure
          npx cdk deploy MLAppStack-Prod \
            -c environment=prod \
            -c applicationOrigin='${{ vars.APPLICATION_ORIGIN }}' \
            -c cognitoDomainPrefix='${{ vars.COGNITO_DOMAIN_PREFIX }}' \
            --parameters ApprovedBedrockModelArn='${{ vars.APPROVED_BEDROCK_MODEL_ARN }}' \
            --parameters ClassifierEndpointName='${{ vars.CLASSIFIER_ENDPOINT_NAME }}' \
            --require-approval never

  release-frontend:
    needs: deploy-infrastructure
    environment: production
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ vars.AWS_AMPLIFY_RELEASE_ROLE_ARN }}
          aws-region: ${{ env.AWS_REGION }}
      - run: >-
          aws amplify start-job
          --app-id '${{ vars.AMPLIFY_APP_ID }}'
          --branch-name main
          --job-type RELEASE

7.3 Environment Promotion Strategy

Promote builds through three stages with explicit quality gates. No code reaches production without passing development and staging validation.

Stage 1
Development
  • Feature development
  • Unit testing
  • Integration testing
  • Code review
Stage 2
Staging
  • End-to-end testing
  • Performance testing
  • Security scanning
  • UAT sign-off
Stage 3
Production
  • Blue-green deploy
  • Health checks
  • Monitoring alerts
  • Rollback capability

deploy.sh — Promote to any environment

sh
scripts/deploy.sh
#!/usr/bin/env bash
# Usage: ./scripts/deploy.sh [dev|staging|prod] [region]
set -euo pipefail

ENVIRONMENT=${1:-dev}
REGION=${2:-us-east-1}

case "$ENVIRONMENT" in
  dev)     STACK_NAME='MLAppStack-Dev';     AMPLIFY_BRANCH='dev' ;;
  staging) STACK_NAME='MLAppStack-Staging'; AMPLIFY_BRANCH='staging' ;;
  prod)    STACK_NAME='MLAppStack-Prod';    AMPLIFY_BRANCH='main' ;;
  *) echo 'Error: environment must be dev, staging, or prod' >&2; exit 1 ;;
esac

: "${AMPLIFY_APP_ID:?Set AMPLIFY_APP_ID}"
: "${APPLICATION_ORIGIN:?Set APPLICATION_ORIGIN}"
: "${COGNITO_DOMAIN_PREFIX:?Set COGNITO_DOMAIN_PREFIX}"
: "${APPROVED_BEDROCK_MODEL_ARN:?Set APPROVED_BEDROCK_MODEL_ARN}"
: "${CLASSIFIER_ENDPOINT_NAME:?Set CLASSIFIER_ENDPOINT_NAME}"

export AWS_REGION="$REGION"
export CDK_DEFAULT_REGION="$REGION"

(
  cd infrastructure
  npm ci
  npm run build
  npx cdk deploy "$STACK_NAME" \
    -c environment="$ENVIRONMENT" \
    -c applicationOrigin="$APPLICATION_ORIGIN" \
    -c cognitoDomainPrefix="$COGNITO_DOMAIN_PREFIX" \
    --parameters ApprovedBedrockModelArn="$APPROVED_BEDROCK_MODEL_ARN" \
    --parameters ClassifierEndpointName="$CLASSIFIER_ENDPOINT_NAME" \
    --require-approval never
)

query_output() {
  aws cloudformation describe-stacks \
    --stack-name "$STACK_NAME" \
    --query "Stacks[0].Outputs[?OutputKey==\`$1\`].OutputValue | [0]" \
    --output text
}

API_URL=$(query_output ApiGatewayUrl)
USER_POOL_ID=$(query_output UserPoolId)
CLIENT_ID=$(query_output UserPoolClientId)
COGNITO_DOMAIN=$(query_output CognitoDomain)
API_SCOPE=$(query_output CognitoApiScope)

case "$ENVIRONMENT" in
  prod) ENV_FILE='frontend/src/environments/environment.prod.ts' ;;
  *)    ENV_FILE="frontend/src/environments/environment.${ENVIRONMENT}.ts" ;;
esac

IS_PROD=false
[[ "$ENVIRONMENT" == 'prod' ]] && IS_PROD=true

cat > "$ENV_FILE" <<EOF
export const environment = {
  production: ${IS_PROD},
  cognito: {
    userPoolId: '${USER_POOL_ID}',
    userPoolWebClientId: '${CLIENT_ID}',
    domain: '${COGNITO_DOMAIN}',
    region: '${REGION}',
    apiScope: '${API_SCOPE}',
  },
  api: {
    baseUrl: '${API_URL}',
    region: '${REGION}',
  },
} as const;
EOF

(
  cd frontend
  npm ci
  npm run "build:${ENVIRONMENT}"
)

aws amplify start-job \
  --app-id "$AMPLIFY_APP_ID" \
  --branch-name "$AMPLIFY_BRANCH" \
  --job-type RELEASE

echo "Deployment complete: $STACK_NAME"
echo "API URL: $API_URL"
echo "User pool: $USER_POOL_ID"
📋 Required GitHub Secrets
  • AWS_DEPLOY_ROLE_ARN (GitHub environment variable)
  • AWS_AMPLIFY_RELEASE_ROLE_ARN (GitHub environment variable)
  • AMPLIFY_APP_ID (GitHub environment variable)
  • DEV_AMPLIFY_APP_ID
  • STAGING_AMPLIFY_APP_ID
  • PROD_AMPLIFY_APP_ID
✅ Pre-deploy Checklist
  • Bedrock model access enabled in Console
  • Cognito domain prefix matches environment.ts
  • CORS origins updated to your Amplify domain
  • dataTraceEnabled: false confirmed
  • Lambda IAM roles scoped to specific ARNs
  • Client model IDs disabled; operation-to-resource allowlists enforced server-side
  • Long-running inference uses asynchronous job orchestration
  • Entra ID tenant ID in SAML metadata URL replaced

8. Best Practices and Considerations

8.1 Security Best Practices

Network-boundary accuracy: Bedrock and SageMaker service endpoints are AWS-managed services and should not be drawn inside a customer subnet. When private service access is required, place the Lambda function and interface VPC endpoints inside the VPC, apply endpoint policies and security groups, and show the managed service outside the VPC boundary.

Authentication and Authorization

  • Multi-Factor Authentication: Enforce MFA for all users, especially administrators
  • Token Management: Implement short-lived access tokens (1 hour) with secure refresh token rotation
  • Principle of Least Privilege: Grant minimum necessary permissions to users and services
  • Regular Access Reviews: Conduct quarterly reviews of user permissions and group memberships
  • Session Management: Implement proper session timeout and concurrent session limits

API Security

  • Input Validation: Validate all inputs at API Gateway and Lambda function levels
  • Rate Limiting: Implement aggressive rate limiting to prevent abuse and DDoS attacks
  • Request Size Limits: Set appropriate payload size limits for ML model inputs
  • CORS Configuration: Configure restrictive CORS policies for production environments
  • API Versioning: Implement proper API versioning to maintain backward compatibility

Data Protection

  • Encryption at Rest: Enable encryption for all data stores (S3, DynamoDB, CloudWatch Logs)
  • Encryption in Transit: Enforce TLS 1.2 minimum (CloudFront policy: TLSv1.2_2021); TLS 1.3 negotiated where clients support it. Implement certificate pinning in mobile clients.
  • Key Management: Use AWS KMS with customer-managed keys and implement key rotation
  • Data Classification: Classify data based on sensitivity and apply appropriate protection measures
  • Data Retention: Implement data retention policies and secure deletion procedures

Infrastructure Security

  • Network Segmentation: Use VPCs, private subnets, and security groups for network isolation
  • WAF Rules: Implement comprehensive WAF rules including OWASP Top 10 protection
  • Security Groups: Configure restrictive security groups with minimal required access
  • VPC Endpoints: Use VPC endpoints for AWS service communication to avoid internet routing
  • CloudTrail Logging: Enable comprehensive CloudTrail logging with log file validation

8.2 Performance Optimization

Frontend Optimization

  • Code Splitting: Implement lazy loading for Angular modules and components
  • Bundle Optimization: Use Angular CLI build optimizations and tree shaking
  • Caching Strategy: Implement proper HTTP caching headers and service worker caching
  • Image Optimization: Use WebP format and responsive images with proper sizing
  • CDN Configuration: Optimize CloudFront caching policies and edge locations

API Performance

  • Lambda Optimization: Optimize Lambda function memory allocation and execution time
  • Connection Pooling: Implement connection pooling for database and external service connections
  • Caching: Implement Redis/ElastiCache for frequently accessed data
  • Async Processing: Use SQS/SNS for asynchronous ML model processing
  • Compression: Enable GZIP compression for API responses

ML Service Optimization

  • Model Optimization: Use SageMaker Compilation Jobs (formerly Neo) for model optimization and hardware-specific compilation
  • Endpoint Configuration: Configure appropriate instance types and auto-scaling policies
  • Batch Processing: Implement batch inference for bulk predictions
  • Model Caching: Cache model predictions for identical inputs
  • Multi-Model Endpoints: Use multi-model endpoints for cost optimization

8.3 Monitoring and Alerting

Application Monitoring

  • Real User Monitoring: Implement RUM to track actual user experience and performance
  • Error Tracking: Use CloudWatch Insights and X-Ray for distributed tracing
  • Performance Metrics: Monitor Core Web Vitals and application-specific metrics
  • Custom Dashboards: Create business-specific dashboards for stakeholders
  • Synthetic Monitoring: Implement synthetic tests for critical user journeys

Infrastructure Monitoring

  • Resource Utilization: Monitor CPU, memory, and network utilization across all services
  • Cost Monitoring: Implement cost alerts and budget monitoring for AWS resources
  • Security Monitoring: Monitor for security events and anomalous behavior
  • Availability Monitoring: Track service availability and uptime metrics
  • Capacity Planning: Monitor trends for proactive capacity planning

ML Model Monitoring

  • Model Performance: Monitor model accuracy, latency, and throughput metrics
  • Data Drift Detection: Implement monitoring for input data distribution changes
  • Model Drift Detection: Monitor for model performance degradation over time
  • Prediction Monitoring: Track prediction distributions and anomalies
  • A/B Testing: Implement A/B testing framework for model comparisons

9. Troubleshooting and Monitoring

Operational objective: Troubleshooting must correlate the browser session, Cognito/Entra federation, API Gateway request, Lambda execution, asynchronous job, and model invocation. Use structured logs, request and correlation IDs, service metrics, traces, alarms, and documented runbooks. Do not log access tokens, SAML assertions, prompts, model inputs, or sensitive model outputs unless an approved redaction and retention policy explicitly permits it.

9.1 Common Issues and Solutions

Authentication, Federation, and Authorization

Issue: API CORS failure

Symptoms: The browser blocks an API request or preflight request and reports a CORS-policy error.

Likely causes: The SPA origin is not explicitly allowed; Authorization is missing from allowed headers; the OPTIONS method is absent; or gateway/integration error responses omit CORS headers.

Resolution:

  • • Match the exact SPA origin; avoid wildcard origins when credentials or authorization headers are used.
  • • Allow the required methods and headers, including Authorization and Content-Type.
  • • Ensure preflight OPTIONS succeeds without requiring user authorization.
  • • Add CORS headers to API Gateway gateway responses and Lambda error responses.
  • • Confirm that AWS WAF is not blocking the preflight request.

Issue: Cognito or Entra redirect/federation failure

Symptoms: Redirect loop, invalid redirect URI, SAML error, PKCE failure, or the browser returns to the SPA without a usable session.

Likely causes: Callback/logout URL mismatch, incorrect Cognito domain, unsupported app-client IdP, Entra ACS/entity-ID mismatch, expired SAML assertion, invalid state/nonce, or PKCE verifier mismatch.

Resolution:

  • • Compare the exact callback and logout URLs in Cognito with the browser URL, including scheme, host, port, path, and trailing slash.
  • • Verify the Cognito user-pool domain and that the Entra SAML provider is enabled on the app client.
  • • Verify Entra’s Cognito ACS URL and service-provider entity ID.
  • • Inspect Entra sign-in logs and Cognito authentication events for Conditional Access, MFA, attribute-mapping, and SAML assertion failures.
  • • Validate browser clock, state, nonce, authorization code, and PKCE verifier handling.

Issue: 401 from the Cognito authorizer or 403 from application policy

Symptoms: API Gateway returns 401, or Lambda/application policy returns 403.

Likely causes: Expired token, wrong issuer, wrong app client, wrong token type, missing OAuth scope, or missing entitlement/group mapping.

Resolution:

  • • For API access, verify iss, token_use=access, client_id, exp, iat, and the required scope such as ml-api/invoke.
  • • Do not substitute an ID token for the access token.
  • • Verify the app-client ID, user-pool ID, API authorizer, and method authorization scopes.
  • • For 403 responses after successful token validation, verify Entra app-role/group mapping and application-specific resource authorization.
  • • Use API Gateway access logs, request IDs, Cognito/Entra logs, and application decision logs; native-authorizer failures may otherwise appear as generic responses.

API Gateway, Lambda, and Asynchronous Processing

Issue: 504 integration timeout

Symptoms: API Gateway returns 504 while Lambda or a downstream model may continue processing.

Likely causes: The integration did not return a usable response within the configured timeout because of Lambda duration, cold start, SageMaker/Bedrock latency, dependency timeout, retry amplification, or malformed integration response.

Resolution:

  • • Compare API Gateway Latency and IntegrationLatency with Lambda duration and downstream service latency.
  • • Keep bounded synchronous inference within the configured API timeout and apply explicit downstream time budgets.
  • • Use an asynchronous design for long-running jobs: submission Lambda → SQS or Step Functions → worker/model → durable result store → status API or callback.
  • • Add idempotency keys so client retries do not create duplicate inference jobs.
  • • Use SNS only when event fan-out or notification delivery is required; use SQS for durable work buffering.

Issue: 429 throttling

Symptoms: API Gateway, Lambda, Bedrock, SageMaker, or SQS-related requests are throttled.

Resolution:

  • • Identify the throttling layer from API access logs, Lambda Throttles, Bedrock/SageMaker error metrics, and service quotas.
  • • Apply exponential backoff with jitter only to retryable, idempotent operations.
  • • Use reserved concurrency to protect downstream systems and SQS to absorb bursts.
  • • Review API usage plans, account-level quotas, Lambda concurrency, model quotas, and autoscaling capacity.
  • • Alarm on sustained throttle rate, not a single isolated event.

Issue: Asynchronous jobs are delayed, duplicated, or stuck

  • • Monitor SQS ApproximateAgeOfOldestMessage, visible messages, in-flight messages, and DLQ depth.
  • • Monitor Step Functions failed, timed-out, and aborted executions.
  • • Verify visibility timeout exceeds worker processing time and configure bounded retries plus a DLQ.
  • • Persist job state and enforce idempotency at submission and completion.
  • • Alert on stale jobs and reconcile durable job state against queue/workflow state.

SageMaker and Amazon Bedrock

Issue: SageMaker endpoint error or latency regression

  • • Verify endpoint and production-variant status, endpoint configuration, model artifacts, image, and input content type.
  • • Inspect Invocations, Invocation4XXErrors, Invocation5XXErrors, InvocationModelErrors, ModelLatency, and OverheadLatency.
  • • Use the AWS/SageMaker namespace with EndpointName and VariantName dimensions; ModelLatency is reported in microseconds.
  • • Inspect instance CPU/GPU/memory, autoscaling capacity, data-capture failures, and model-monitor findings where enabled.
  • • Validate input schema and preprocessing against the deployed model contract.

Issue: Bedrock access, throttling, or model-availability failure

  • • Verify the model or inference-profile ID and availability in the selected Region.
  • • Verify bedrock:InvokeModel or the relevant streaming permission, plus SCPs, permission boundaries, resource policies, and guardrail permissions.
  • • Check Marketplace entitlement/subscription requirements, Anthropic first-use requirements where applicable, model lifecycle state, and account quotas.
  • • Monitor invocation count, latency, client/server errors, throttles, token usage, and guardrail interventions.
  • • Enable model invocation logging only with approved encryption, redaction, access, and retention controls.

Amplify Hosting, CloudFront, and AWS WAF

  • Amplify build/deploy: Inspect build logs, lock-file consistency, runtime version, environment variables, artifact directory, branch settings, and SPA rewrite rules.
  • Custom domain/TLS: Verify DNS ownership, certificate status, domain association, redirect rules, and deployment propagation.
  • CloudFront: Monitor request count, 4XX/5XX rates, cache-hit rate, origin latency, and deployment changes.
  • AWS WAF: Monitor allowed, blocked, counted, CAPTCHA/challenge, rate-based-rule, and managed-rule-label activity. Review sampled requests and WAF logs for false positives.
  • Security response: Correlate WAF labels, API request IDs, Cognito principal, and application correlation ID without logging bearer tokens or sensitive payloads.

9.2 Observability Architecture

End-to-End Telemetry and Incident Flow

Application PathSPA, API, Lambda, ML TelemetryMetrics, logs, traces CloudWatchDashboards + alarms SNS / IncidentPager + ticket RunbookTriage + containment RemediationRollback, scale, isolate Post-IncidentEvidence + actions 1 2 3 4 5 6
Sequence legend
  1. 1: Every application component emits structured, privacy-filtered metrics, logs, and traces with request and correlation IDs.
  2. 2: Telemetry is centralized into CloudWatch dashboards, Logs Insights, alarms, and trace views.
  3. 3: Actionable alarm states create an incident through SNS and the organization’s paging/ticketing integration.
  4. 4: The responder follows the service-specific runbook, validates scope and severity, and applies containment.
  5. 5: Remediation may include rollback, quota/capacity adjustment, queue draining, model failover, or access isolation.
  6. 6: The incident is closed only after evidence capture, root-cause analysis, corrective actions, and monitoring updates.

9.3 Monitoring Baseline CloudWatch

The production baseline uses service metrics, metric math, structured logs, traces, and alarms tied to SLOs. The example values below are placeholders; calibrate them from observed traffic, error budgets, model latency objectives, environment criticality, and expected spend.

LayerMinimum signalsOperational purpose
Amplify / CloudFrontBuild/deploy failures, request count, 4XX/5XX rate, cache-hit rate, origin latencyDetect failed releases, broken rewrites, domain/TLS problems, and delivery regressions
AWS WAFAllowed, blocked, counted, rate-based rule, managed-rule labels, sampled requestsDetect attack traffic and false positives
Cognito / EntraAuthentication failures, redirect/SAML errors, Conditional Access denials, entitlement failuresDistinguish authentication, federation, and authorization faults
API GatewayCount, 4XX/5XX rate, Latency, IntegrationLatency, access logs, per-route statusSeparate client, authorization, gateway, and integration failures
LambdaInvocations, Errors, Throttles, p95/p99 Duration, ConcurrentExecutions, timeout and dependency metricsDetect code defects, saturation, and downstream latency
Async pathSQS age/depth/DLQ, Step Functions failed/timed-out/aborted, stale-job countDetect backlog, poison messages, and workflow failure
SageMakerInvocations, 4XX/5XX/model errors, ModelLatency, OverheadLatency, capacity and model-monitor findingsDetect endpoint, model, capacity, and drift issues
BedrockInvocations, latency, client/server errors, throttles, token usage, guardrail interventionsDetect model access, quota, safety, latency, and cost issues
CostAWS Budgets, Cost Anomaly Detection, account/service forecastsDetect unexpected spend and apply governed cost actions

Corrected CloudWatch dashboard JSON

DeploymentPaste this JSON into CloudWatch Dashboards, or deploy the JSON with cloudwatch.CfnDashboard. The L2 cloudwatch.Dashboard uses widget objects and addWidgets(); it does not accept a dashboardBody property.
{ }
cloudwatch/dashboard.json
{
  "widgets": [
    {
      "type": "metric",
      "width": 12,
      "height": 6,
      "properties": {
        "title": "API Gateway — Traffic, Errors, and Latency",
        "region": "us-east-1",
        "period": 300,
        "view": "timeSeries",
        "metrics": [
          ["AWS/ApiGateway", "Count", "ApiName", "ML App API", {"id": "requests", "stat": "Sum"}],
          [".", "4XXError", ".", ".", {"id": "e4", "stat": "Sum", "visible": false}],
          [".", "5XXError", ".", ".", {"id": "e5", "stat": "Sum", "visible": false}],
          [{"expression": "100*e4/MAX([requests,1])", "label": "4XX rate (%)", "id": "r4"}],
          [{"expression": "100*e5/MAX([requests,1])", "label": "5XX rate (%)", "id": "r5"}],
          [".", "Latency", ".", ".", {"stat": "p95", "label": "Latency p95"}],
          [".", "IntegrationLatency", ".", ".", {"stat": "p95", "label": "Integration latency p95"}]
        ]
      }
    },
    {
      "type": "metric",
      "width": 12,
      "height": 6,
      "properties": {
        "title": "Lambda — Health and Saturation",
        "region": "us-east-1",
        "period": 300,
        "metrics": [
          ["AWS/Lambda", "Invocations", "FunctionName", "MLProcessorFunction-prod", {"stat": "Sum"}],
          [".", "Errors", ".", ".", {"stat": "Sum"}],
          [".", "Throttles", ".", ".", {"stat": "Sum"}],
          [".", "Duration", ".", ".", {"stat": "p95"}],
          [".", "ConcurrentExecutions", ".", ".", {"stat": "Maximum"}]
        ]
      }
    },
    {
      "type": "metric",
      "width": 12,
      "height": 6,
      "properties": {
        "title": "SageMaker Endpoint — Invocations, Errors, and Latency",
        "region": "us-east-1",
        "period": 300,
        "metrics": [
          ["AWS/SageMaker", "Invocations", "EndpointName", "approved-classifier-endpoint", "VariantName", "AllTraffic", {"stat": "Sum"}],
          [".", "Invocation4XXErrors", ".", ".", ".", ".", {"stat": "Sum"}],
          [".", "Invocation5XXErrors", ".", ".", ".", ".", {"stat": "Sum"}],
          [".", "InvocationModelErrors", ".", ".", ".", ".", {"stat": "Sum"}],
          [".", "ModelLatency", ".", ".", ".", ".", {"stat": "p95", "label": "Model latency p95 (µs)"}],
          [".", "OverheadLatency", ".", ".", ".", ".", {"stat": "p95", "label": "Overhead latency p95 (µs)"}]
        ]
      }
    },
    {
      "type": "metric",
      "width": 12,
      "height": 6,
      "properties": {
        "title": "Async Queue — Backlog and DLQ",
        "region": "us-east-1",
        "period": 300,
        "metrics": [
          ["AWS/SQS", "ApproximateNumberOfMessagesVisible", "QueueName", "ml-jobs-prod", {"stat": "Maximum"}],
          [".", "ApproximateAgeOfOldestMessage", ".", ".", {"stat": "Maximum"}],
          [".", "ApproximateNumberOfMessagesNotVisible", ".", ".", {"stat": "Maximum"}],
          ["AWS/SQS", "ApproximateNumberOfMessagesVisible", "QueueName", "ml-jobs-dlq-prod", {"stat": "Maximum", "label": "DLQ depth"}]
        ]
      }
    },
    {
      "type": "log",
      "width": 24,
      "height": 6,
      "properties": {
        "title": "Recent Lambda errors by correlation ID",
        "region": "us-east-1",
        "view": "table",
        "query": "SOURCE '/aws/lambda/MLProcessorFunction-prod' | fields @timestamp, level, correlationId, requestId, errorType, message | filter level = 'ERROR' | sort @timestamp desc | limit 50"
      }
    }
  ]
}

Corrected CDK alarms and dashboard deployment

TS
lib/monitoring-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as cloudwatch from 'aws-cdk-lib/aws-cloudwatch';
import * as actions from 'aws-cdk-lib/aws-cloudwatch-actions';
import * as sns from 'aws-cdk-lib/aws-sns';
import * as subscriptions from 'aws-cdk-lib/aws-sns-subscriptions';
import { Construct } from 'constructs';

export interface MonitoringStackProps extends cdk.StackProps {
  readonly alertEmail: string;
  readonly apiName: string;
  readonly lambdaFunctionName: string;
  readonly sageMakerEndpointName: string;
  readonly dashboardBody: string;
}

export class MonitoringStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: MonitoringStackProps) {
    super(scope, id, props);

    const alerts = new sns.Topic(this, 'OperationalAlerts', {
      enforceSSL: true,
    });
    alerts.addSubscription(new subscriptions.EmailSubscription(props.alertEmail));
    const notify = new actions.SnsAction(alerts);

    const requests = new cloudwatch.Metric({
      namespace: 'AWS/ApiGateway', metricName: 'Count',
      dimensionsMap: { ApiName: props.apiName },
      statistic: 'Sum', period: cdk.Duration.minutes(5),
    });
    const errors4xx = new cloudwatch.Metric({
      namespace: 'AWS/ApiGateway', metricName: '4XXError',
      dimensionsMap: { ApiName: props.apiName },
      statistic: 'Sum', period: cdk.Duration.minutes(5),
    });
    const errorRate4xx = new cloudwatch.MathExpression({
      expression: '100 * e4 / MAX([req, 1])',
      usingMetrics: { e4: errors4xx, req: requests },
      label: 'API 4XX rate (%)', period: cdk.Duration.minutes(5),
    });
    errorRate4xx.createAlarm(this, 'Api4xxRateAlarm', {
      threshold: 5,
      evaluationPeriods: 3,
      datapointsToAlarm: 2,
      comparisonOperator: cloudwatch.ComparisonOperator.GREATER_THAN_THRESHOLD,
      treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
    }).addAlarmAction(notify);

    new cloudwatch.Metric({
      namespace: 'AWS/Lambda', metricName: 'Errors',
      dimensionsMap: { FunctionName: props.lambdaFunctionName },
      statistic: 'Sum', period: cdk.Duration.minutes(5),
    }).createAlarm(this, 'LambdaErrorsAlarm', {
      threshold: 1, evaluationPeriods: 3, datapointsToAlarm: 2,
      treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
    }).addAlarmAction(notify);

    new cloudwatch.Metric({
      namespace: 'AWS/SageMaker', metricName: 'ModelLatency',
      dimensionsMap: {
        EndpointName: props.sageMakerEndpointName,
        VariantName: 'AllTraffic',
      },
      statistic: 'p95', period: cdk.Duration.minutes(5),
    }).createAlarm(this, 'SageMakerLatencyAlarm', {
      threshold: 5_000_000, // 5 seconds, expressed in microseconds
      evaluationPeriods: 3, datapointsToAlarm: 2,
      treatMissingData: cloudwatch.TreatMissingData.NOT_BREACHING,
    }).addAlarmAction(notify);

    new cloudwatch.CfnDashboard(this, 'OperationsDashboard', {
      dashboardName: 'ML-App-Operations',
      dashboardBody: props.dashboardBody,
    });
  }
}
Billing monitoringCreate billing alarms in a dedicated stack deployed to us-east-1 after enabling billing alerts in the payer/management account. Prefer AWS Budgets and Cost Anomaly Detection for governed cost thresholds and forecast-based alerts. Merely setting a metric region does not relocate an alarm deployed in another Region.

9.4 Logging, Tracing, SLOs, and Runbooks

Structured logging

  • • JSON logs with timestamp, level, service, environment, request ID, correlation ID, route, operation, status, latency, and error code.
  • • Redact tokens, SAML assertions, secrets, prompts, files, PII, and model output.
  • • Set explicit retention, encryption, access, and export controls.

Tracing

  • • Propagate a correlation ID from the SPA through API Gateway, Lambda, queues/workflows, and model calls.
  • • Use AWS X-Ray or OpenTelemetry where supported.
  • • Record downstream latency and retry count without recording sensitive payloads.

SLOs and alarms

  • • Define availability, successful-request rate, p95/p99 latency, job-completion time, and model-quality objectives.
  • • Use error budgets, M-of-N alarms, anomaly detection, warning/critical thresholds, and composite alarms.
  • • Include alarm owner, runbook URL, environment, and customer impact in the alarm description.

Runbooks and incident response

  • • Document triage queries, rollback, queue draining, capacity changes, model fallback, and access containment.
  • • Test runbooks through game days and synthetic canaries.
  • • Capture timeline, evidence, root cause, corrective actions, and monitoring gaps after every material incident.

10. Appendix

10.1 Reference Links

AWS Documentation

  • AWS Amplify: https://docs.aws.amazon.com/amplify/
  • Amazon Cognito: https://docs.aws.amazon.com/cognito/
  • API Gateway: https://docs.aws.amazon.com/apigateway/
  • AWS Lambda: https://docs.aws.amazon.com/lambda/
  • Amazon SageMaker: https://docs.aws.amazon.com/sagemaker/
  • Amazon Bedrock: https://docs.aws.amazon.com/bedrock/
  • AWS CDK: https://docs.aws.amazon.com/cdk/
  • AWS WAF: https://docs.aws.amazon.com/waf/

Angular and Frontend

  • Angular Documentation: https://angular.io/docs
  • Angular Material: https://material.angular.io/
  • AWS Amplify JavaScript: https://docs.amplify.aws/javascript/
  • TypeScript Handbook: https://www.typescriptlang.org/docs/
  • RxJS Documentation: https://rxjs.dev/guide/overview

Security and Compliance

  • OAuth 2.0 Specification: https://tools.ietf.org/html/rfc6749
  • OpenID Connect: https://openid.net/connect/
  • JWT Specification: https://tools.ietf.org/html/rfc7519
  • OWASP Top 10: https://owasp.org/www-project-top-ten/
  • AWS Security Best Practices: https://aws.amazon.com/security/security-resources/

Machine Learning

  • SageMaker Examples: https://github.com/aws/amazon-sagemaker-examples
  • Bedrock User Guide: https://docs.aws.amazon.com/bedrock/latest/userguide/
  • ML Best Practices: https://aws.amazon.com/machine-learning/ml-best-practices/
  • Model Deployment Patterns: https://ml-ops.org/

10.2 Glossary

API Gateway: AWS service for creating, publishing, maintaining, monitoring, and securing REST and WebSocket APIs
AWS Amplify: Development platform for building secure, scalable mobile and web applications
Amazon Bedrock: Fully managed service for accessing foundation models via APIs
CDK (Cloud Development Kit): Framework for defining cloud infrastructure using familiar programming languages
CloudFront: AWS content delivery network (CDN) service for fast content delivery
Cognito: AWS service for user authentication, authorization, and user management
CORS (Cross-Origin Resource Sharing): Mechanism that allows restricted resources on a web page to be requested from another domain
JWT (JSON Web Token): Compact, URL-safe means of representing claims to be transferred between two parties
Lambda: AWS serverless compute service that runs code in response to events
RBAC (Role-Based Access Control): Method of regulating access to resources based on the roles of individual users
SageMaker: AWS machine learning platform for building, training, and deploying ML models
SAML (Security Assertion Markup Language): XML-based standard for exchanging authentication and authorization data
SPA (Single Page Application): Web application that loads a single HTML page and dynamically updates content
WAF (Web Application Firewall): Security service that protects web applications from common web exploits

10.3 Version History

Version Date Author Changes
2.4 July 2026 AI Security Architecture Review Corrected and expanded troubleshooting, observability, dashboards, alarms, async monitoring, and incident-response guidance
1.0 July 2025 Technical Documentation Team Initial release with complete implementation guide
0.9 June 2025 Technical Documentation Team Beta release for internal review and testing
0.8 May 2025 Technical Documentation Team Added security architecture and compliance sections
0.7 April 2025 Technical Documentation Team Completed implementation guide and deployment sections
0.6 March 2025 Technical Documentation Team Added data flow architecture and ML integration details
0.5 February 2025 Technical Documentation Team Initial architecture overview and authentication flows

Document Series Navigation

Part 1 AWS Amplify Hosting for ML/AI Services Guide Architecture · Access Patterns · Security Design
Part 2 — You are here AWS Amplify ML Services Integration Guide CDK Stacks · Lambda Code · CI/CD · Deployment
Back to AWS Amplify Hosting for ML/AI Services Guide