Amazon Developer Guides: Mobile Development & API Gateway
Class Notes
Part I: Amazon Mobile App Development using AWS Mobile Services
Overview of AWS Mobile Development
What is AWS Mobile Development? AWS provides a comprehensive suite of mobile services that enable
developers to build, test, and monitor mobile applications with cloud-powered backends. These services
handle common mobile app requirements like user authentication, data storage, push notifications, and
analytics.
Core AWS Mobile Services:
AWS Amplify (unified development platform)
Amazon Cognito (user management and authentication)
AWS AppSync (GraphQL API and real-time data sync)
Amazon DynamoDB (NoSQL database)
Amazon S3 (file storage)
Amazon Pinpoint (analytics and engagement)
AWS Lambda (serverless compute)
AWS Amplify Framework
What is AWS Amplify?
Amplify is a development platform that provides tools and services for building secure, scalable full-stack
applications powered by AWS. It offers both a CLI toolchain and client libraries for mobile and web
development.
Key Components
Amplify CLI:
Project initialization and configuration
Backend resource provisioning
Local development and testing
Deployment automation
Amplify Libraries:
Native iOS (Swift) and Android (Kotlin/Java) libraries
React Native and Flutter support
JavaScript/TypeScript for web applications
Cross-platform API abstractions
Amplify Studio:
Visual development environment
UI component library
Backend management interface
Team collaboration tools
Getting Started with Amplify
Installation and Setup:
bash
# Install Amplify CLI
npm install -g @aws-amplify/cli
# Configure Amplify
amplify configure
# Initialize new project
amplify init
# Add authentication
amplify add auth
# Add API
amplify add api
# Deploy backend
amplify push
Project Structure:
my-app/
├── amplify/ # Backend configuration
│ ├── backend/ # Infrastructure as code
│ └── team-provider-info.json
├── src/
│ ├── aws-exports.js # Auto-generated configuration
│ └── app components
└── package.json
Core Mobile Services Deep Dive
1. Amazon Cognito - User Management
Functionality:
User registration and authentication
Social identity providers (Google, Facebook, Apple)
Multi-factor authentication (MFA)
User pools and identity pools
Fine-grained access control
User Pools vs Identity Pools:
User Pools: User directory service with authentication
Identity Pools: Federated identities with AWS credentials
Implementation Example (React Native):
javascript
import { Auth } from 'aws-amplify';
// Sign up new user
const signUp = async (username, password, email) => {
try {
const { user } = await Auth.signUp({
username,
password,
attributes: { email },
});
return user;
} catch (error) {
console.log('Error signing up:', error);
}
};
// Sign in user
const signIn = async (username, password) => {
try {
const user = await Auth.signIn(username, password);
return user;
} catch (error) {
console.log('Error signing in:', error);
}
};
Advanced Features:
Custom authentication flows
Lambda triggers for user lifecycle events
SAML and OIDC federation
Device tracking and management
2. AWS AppSync - GraphQL API and Real-time Data
What is AppSync? AWS AppSync is a managed GraphQL service that enables real-time data
synchronization and offline capabilities for mobile applications.
Key Features:
Real-time subscriptions
Offline data synchronization
Conflict resolution
Multiple data sources (DynamoDB, Lambda, RDS)
Built-in caching
GraphQL Schema Example:
graphql
type Todo @model @auth(rules: [{allow: owner}]) {
id: ID!
name: String!
description: String
completed: Boolean!
owner: String
}
Client Implementation:
javascript
import { API, graphqlOperation } from 'aws-amplify';
import { createTodo, updateTodo } from './graphql/mutations';
import { listTodos } from './graphql/queries';
import { onCreateTodo } from './graphql/subscriptions';
// Create new todo
const addTodo = async (todoData) => {
try {
const newTodo = await API.graphql(
graphqlOperation(createTodo, { input: todoData })
);
return newTodo;
} catch (error) {
console.log('Error creating todo:', error);
}
};
// Real-time subscription
useEffect(() => {
const subscription = API.graphql(
graphqlOperation(onCreateTodo)
).subscribe({
next: (todoData) => {
// Handle new todo creation
console.log('New todo:', todoData);
}
});
return () => subscription.unsubscribe();
}, []);
3. Amazon DynamoDB - NoSQL Database
Characteristics:
Serverless and fully managed
Single-digit millisecond latency
Automatic scaling
Built-in security features
Global tables for multi-region deployment
Data Modeling Best Practices:
Design around access patterns
Use composite keys effectively
Leverage Global Secondary Indexes (GSI)
Minimize data duplication where possible
Integration with Amplify:
javascript
// Amplify DataStore (offline-first)
import { DataStore } from '@aws-amplify/datastore';
import { Todo } from './models';
// Save data (works offline)
const saveTodo = async (todoData) => {
await DataStore.save(new Todo(todoData));
};
// Query data
const getTodos = async () => {
const todos = await DataStore.query(Todo);
return todos;
};
// Real-time updates
DataStore.observe(Todo).subscribe(msg => {
console.log('Todo updated:', msg.model, msg.opType);
});
4. Amazon S3 - File Storage
Use Cases:
Profile pictures and media uploads
Document storage
Content delivery
Data backup and archiving
Amplify Storage Implementation:
javascript
import { Storage } from 'aws-amplify';
// Upload file
const uploadFile = async (file) => {
try {
const result = await Storage.put('photos/' + file.name, file, {
contentType: file.type,
level: 'private' // public, protected, or private
});
return result;
} catch (error) {
console.log('Error uploading file:', error);
}
};
// Download file
const downloadFile = async (key) => {
try {
const url = await Storage.get(key, { level: 'private' });
return url;
} catch (error) {
console.log('Error downloading file:', error);
}
};
5. Amazon Pinpoint - Analytics and Engagement
Capabilities:
User behavior analytics
Push notifications
Email and SMS campaigns
A/B testing
User segmentation
Analytics Implementation:
javascript
import { Analytics } from 'aws-amplify';
// Record custom events
Analytics.record({
name: 'todo_created',
attributes: {
category: 'productivity',
priority: 'high'
},
metrics: {
count: 1
}
});
// Track user sessions
Analytics.autoTrack('session', {
enable: true,
attributes: {
customAttribute: 'value'
}
});
Mobile App Architecture Patterns
1. Offline-First Architecture
Benefits:
Improved user experience
Reduced network dependency
Better performance
Seamless connectivity transitions
Implementation Strategy:
Local data caching with DataStore
Conflict resolution mechanisms
Background synchronization
Network status monitoring
2. Serverless Backend Architecture
Components:
API Gateway for REST endpoints
Lambda functions for business logic
DynamoDB for data persistence
S3 for file storage
CloudWatch for monitoring
Benefits:
No server management
Automatic scaling
Pay-per-use pricing
High availability
3. Microservices with GraphQL
Advantages:
Single endpoint for multiple data sources
Efficient data fetching
Real-time capabilities
Type safety and introspection
Platform-Specific Considerations
iOS Development
Swift Integration:
swift
import Amplify
import AmplifyPlugins
// Configure Amplify
func configureAmplify() {
do {
try Amplify.add(plugin: AWSCognitoAuthPlugin())
try Amplify.add(plugin: AWSAPIPlugin())
try Amplify.add(plugin: AWSDataStorePlugin(modelRegistration: AmplifyModels()))
try Amplify.configure()
} catch {
print("Failed to initialize Amplify:", error)
}
}
Android Development
Kotlin Integration:
kotlin
import com.amplifyframework.core.Amplify
import com.amplifyframework.auth.cognito.AWSCognitoAuthPlugin
import com.amplifyframework.api.aws.AWSApiPlugin
// Initialize Amplify
private fun configureAmplify() {
try {
Amplify.addPlugin(AWSCognitoAuthPlugin())
Amplify.addPlugin(AWSApiPlugin())
Amplify.configure(applicationContext)
} catch (error: AmplifyException) {
Log.e("Amplify", "Failed to configure", error)
}
}
React Native Considerations
Performance Optimization:
Use FlashList for large datasets
Implement proper image caching
Optimize bundle size
Handle deep linking properly
Part II: Amazon API Gateway Developer Guide
Overview of Amazon API Gateway
What is API Gateway? Amazon API Gateway is a fully managed service that makes it easy for developers
to create, publish, maintain, monitor, and secure APIs at any scale. It acts as a "front door" for applications
to access data, business logic, or functionality from backend services.
Key Features:
RESTful and WebSocket API support
Request/response transformation
Authentication and authorization
Rate limiting and throttling
Monitoring and analytics
API versioning and stages
SDK generation
API Gateway Types
1. REST APIs
Characteristics:
Full-featured API management
Request validation and transformation
Caching capabilities
Comprehensive monitoring
Custom domain names
Use Cases:
Traditional web applications
Mobile app backends
Microservices architecture
Third-party integrations
2. HTTP APIs
Characteristics:
Optimized for serverless workloads
Lower latency and cost
Built-in CORS support
JWT authorizer support
Simplified configuration
Use Cases:
Lambda proxy integrations
Modern serverless applications
Cost-sensitive workloads
Simple proxy use cases
3. WebSocket APIs
Characteristics:
Real-time two-way communication
Connection management
Route-based message handling
Integration with Lambda and other services
Use Cases:
Chat applications
Live dashboards
Gaming applications
IoT device communication
API Gateway Architecture
Core Components
Resources and Methods:
Resources represent API endpoints
Methods define HTTP verbs (GET, POST, PUT, DELETE)
Method execution pipeline includes stages like authorization, validation, integration
Integration Types:
Lambda Proxy: Direct integration with Lambda functions
Lambda Non-Proxy: Custom integration with transformation
HTTP Proxy: Forward requests to HTTP endpoints
AWS Service: Direct integration with AWS services
Mock: Return static responses for testing
Stages and Deployments:
Stages represent different environments (dev, test, prod)
Deployments create snapshots of API configuration
Stage variables enable environment-specific configuration
Request/Response Flow
1. Request Processing Pipeline
Client Request →
Authentication/Authorization →
Request Validation →
Request Transformation →
Integration Request →
Backend Service →
Integration Response →
Response Transformation →
Client Response
2. Method Execution Details
Request Validation:
Parameter validation
Request body validation against JSON Schema
Required parameter enforcement
Mapping Templates:
Transform request format using Velocity Template Language (VTL)
Extract data from headers, query parameters, body
Convert between different data formats
Authentication and Authorization
1. IAM Authentication
Use Cases:
Service-to-service communication
AWS SDK usage
Internal APIs
Implementation:
javascript
// AWS SDK v3 example
import { APIGateway } from '@aws-sdk/client-api-gateway';
import { fromCognitoIdentityPool } from '@aws-sdk/credential-provider-cognito-identity';
const credentials = fromCognitoIdentityPool({
clientId: 'your-identity-pool-id',
identityPoolId: 'your-identity-pool-id'
});
const apiGateway = new APIGateway({
region: 'us-east-1',
credentials
});
2. Cognito User Pool Authorizers
Configuration:
Token validation against Cognito User Pool
Automatic JWT verification
Claims-based authorization
Lambda Authorizer Example:
javascript
exports.handler = async (event) => {
const token = event.authorizationToken;
// Validate token logic here
const isValid = validateToken(token);
if (isValid) {
return {
principalId: 'user-id',
policyDocument: {
Version: '2012-10-17',
Statement: [{
Action: 'execute-api:Invoke',
Effect: 'Allow',
Resource: event.methodArn
}]
}
};
} else {
throw new Error('Unauthorized');
}
};
3. API Keys and Usage Plans
API Key Management:
Generate and distribute API keys
Associate keys with usage plans
Monitor key usage and quotas
Usage Plans:
Define throttle limits
Set quota restrictions
Manage different tiers of access
Integration Patterns
1. Lambda Integration
Proxy Integration:
javascript
// Lambda function for proxy integration
exports.handler = async (event) => {
const { httpMethod, path, queryStringParameters, body } = event;
// Process request
let response;
switch (httpMethod) {
case 'GET':
response = await handleGet(queryStringParameters);
break;
case 'POST':
response = await handlePost(JSON.parse(body));
break;
default:
response = { message: 'Method not allowed' };
}
return {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*'
},
body: JSON.stringify(response)
};
};
2. Direct AWS Service Integration
DynamoDB Integration Example:
json
{
"TableName": "Users",
"Key": {
"userId": {
"S": "$input.params('id')"
}
}
}
3. HTTP Integration
Backend Service Integration:
Proxy to existing REST APIs
Transform requests/responses
Add authentication layers
Implement circuit breaker patterns
Monitoring and Analytics
1. CloudWatch Integration
Metrics Available:
Request count and latency
Error rates (4XX, 5XX)
Integration latency
Cache hit/miss rates
Custom Metrics:
Business-specific metrics
Performance indicators
Usage patterns
2. AWS X-Ray Tracing
Benefits:
End-to-end request tracing
Performance bottleneck identification
Error analysis
Service dependency mapping
Implementation:
javascript
const AWSXRay = require('aws-xray-sdk-core');
const AWS = AWSXRay.captureAWS(require('aws-sdk'));
exports.handler = async (event) => {
const segment = AWSXRay.getSegment();
const subsegment = segment.addNewSubsegment('database-query');
try {
// Database operation
const result = await performDatabaseQuery();
subsegment.close();
return result;
} catch (error) {
subsegment.addError(error);
subsegment.close();
throw error;
}
};
Advanced Features
1. Request/Response Transformation
Mapping Templates:
vtl
## Request mapping template
{
"userId": "$input.params('id')",
"requestTime": "$context.requestTime",
"sourceIp": "$context.identity.sourceIp",
#if($input.json('$.name'))
"name": "$input.json('$.name')",
#end
"body": $input.json('$')
}
2. Caching
Cache Configuration:
Per-stage cache settings
TTL configuration
Cache key customization
Cache invalidation strategies
Cache Key Example:
GET /users?status=active&page=1
Cache Key: method.request.querystring.status,method.request.querystring.page
3. CORS Configuration
Automatic CORS:
javascript
// For HTTP APIs (automatic)
const corsOptions = {
allowOrigins: ['https://mydomain.com'],
allowMethods: ['GET', 'POST', 'PUT', 'DELETE'],
allowHeaders: ['content-type', 'authorization']
};
4. Custom Domain Names
Setup Process:
1. Obtain SSL certificate in ACM
2. Create custom domain name in API Gateway
3. Configure DNS mapping
4. Update client applications
Security Best Practices
1. API Security
Enable WAF (Web Application Firewall)
Implement proper authentication
Use HTTPS only
Validate all input data
Implement rate limiting
2. Backend Protection
Use VPC endpoints when possible
Implement least privilege access
Encrypt data in transit and at rest
Regular security audits
3. Monitoring Security
Enable CloudTrail logging
Set up CloudWatch alarms
Monitor for suspicious patterns
Implement automated responses
Cost Optimization
1. Pricing Model Understanding
REST APIs:
Per API call pricing
Data transfer charges
Caching costs
Additional feature costs
HTTP APIs:
Lower per-request cost
Simplified pricing model
No caching charges
2. Optimization Strategies
Choose appropriate API type
Implement efficient caching
Use compression when beneficial
Monitor and optimize usage patterns
Development Best Practices
1. API Design
RESTful Principles:
Use appropriate HTTP methods
Implement proper status codes
Design intuitive resource URIs
Version APIs appropriately
Documentation:
Use OpenAPI/Swagger specifications
Provide comprehensive examples
Maintain up-to-date documentation
Include error response formats
2. Error Handling
Consistent Error Responses:
json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid request parameters",
"details": [
{
"field": "email",
"issue": "Invalid email format"
}
]
}
}
3. Testing Strategies
Unit testing for Lambda functions
Integration testing with API Gateway
Load testing for performance
Security testing for vulnerabilities
Deployment and DevOps
1. Infrastructure as Code
AWS CloudFormation:
yaml
Resources:
MyApi:
Type: AWS::ApiGateway::RestApi
Properties:
Name: MyAPI
Description: My API Gateway
MyResource:
Type: AWS::ApiGateway::Resource
Properties:
RestApiId: !Ref MyApi
ParentId: !GetAtt MyApi.RootResourceId
PathPart: users
AWS SAM (Serverless Application Model):
yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
MyApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
Auth:
DefaultAuthorizer: MyCognitoAuthorizer
Authorizers:
MyCognitoAuthorizer:
UserPoolArn: !GetAtt MyCognitoUserPool.Arn
2. CI/CD Pipeline
Deployment Stages:
1. Code commit triggers build
2. Run tests and validation
3. Deploy to staging environment
4. Run integration tests
5. Deploy to production
6. Monitor deployment health
Integration Between Mobile Services and API Gateway
Complete Mobile Architecture
Backend Architecture
Mobile App →
API Gateway →
Lambda Functions →
DynamoDB/RDS/S3 →
Additional AWS Services
Authentication Flow
Mobile App →
Cognito Authentication →
JWT Token →
API Gateway (Cognito Authorizer) →
Backend Services
Example: Todo App with Full Stack
1. Backend API (API Gateway + Lambda)
javascript
// Lambda function for todo operations
exports.handler = async (event) => {
const { httpMethod, pathParameters, body } = event;
const userId = event.requestContext.authorizer.claims.sub;
switch (httpMethod) {
case 'GET':
return await getTodos(userId);
case 'POST':
return await createTodo(userId, JSON.parse(body));
case 'PUT':
return await updateTodo(userId, pathParameters.id, JSON.parse(body));
case 'DELETE':
return await deleteTodo(userId, pathParameters.id);
}
};
2. Mobile App Integration
javascript
// Configure API Gateway endpoint
const apiConfig = {
endpoints: [
{
name: "TodoAPI",
endpoint: "https://api.example.com/prod",
region: "us-east-1"
}
]
};
// Make authenticated API calls
const getTodos = async () => {
try {
const response = await API.get('TodoAPI', '/todos');
return response;
} catch (error) {
console.error('Error fetching todos:', error);
}
};
Key Takeaways
Mobile Development with AWS
1. Unified Platform: AWS Amplify provides a complete development platform
2. Offline-First: Design for unreliable network conditions
3. Security by Default: Leverage Cognito for robust authentication
4. Real-time Capabilities: Use AppSync for live data synchronization
API Gateway Management
1. Right Tool for the Job: Choose between REST and HTTP APIs based on requirements
2. Security First: Implement proper authentication and authorization
3. Monitor Everything: Use CloudWatch and X-Ray for comprehensive monitoring
4. Design for Scale: Plan for growth with proper caching and throttling
Integration Best Practices
Design APIs with mobile constraints in mind
Implement proper error handling and retry mechanisms
Use GraphQL for efficient data fetching
Leverage AWS services for automatic scaling and high availability