Comprehensive developer toolkit providing reusable skills for Java/Spring Boot, TypeScript/NestJS/React/Next.js, Python, PHP, AWS CloudFormation, AI/RAG, DevOps, and more.
82
82%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Risky
Do not use without reviewing
Complete guide for deploying Java Lambda functions with Serverless Framework, AWS SAM, and CI/CD pipelines.
service: java-lambda-api
provider:
name: aws
runtime: java21
memorySize: 512
timeout: 10
region: ${opt:region, 'us-east-1'}
stage: ${opt:stage, 'dev'}
environment:
STAGE: ${self:provider.stage}
USERS_TABLE: !Ref UsersTable
iam:
role:
statements:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: '*'
- Effect: Allow
Action:
- dynamodb:GetItem
- dynamodb:PutItem
- dynamodb:DeleteItem
- dynamodb:Scan
- dynamodb:Query
Resource: !GetAtt UsersTable.Arn
package:
artifact: build/libs/${self:service}-${self:provider.stage}.jar
functions:
api:
handler: com.example.Handler
events:
- http:
path: /{proxy+}
method: ANY
cors: true
- http:
path: /
method: ANY
cors: true
resources:
Resources:
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: ${self:service}-users-${self:provider.stage}
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
Outputs:
ApiUrl:
Value: !Join ['', ['https://', !Ref ApiGatewayRestApi, '.execute-api.', !Ref 'AWS::Region', '.amazonaws.com/', ${self:provider.stage}]]
Export:
Name: ${self:service}-api-url-${self:provider.stage}service: java-lambda-api
provider:
name: aws
runtime: java21
memorySize: ${self:custom.memorySize.${self:provider.stage}}
timeout: ${self:custom.timeout.${self:provider.stage}}
region: ${opt:region, 'us-east-1'}
stage: ${opt:stage, 'dev'}
environment:
STAGE: ${self:provider.stage}
LOG_LEVEL: ${self:custom.logLevel.${self:provider.stage}}
custom:
memorySize:
dev: 512
staging: 1024
prod: 2048
timeout:
dev: 10
staging: 15
prod: 30
logLevel:
dev: DEBUG
staging: INFO
prod: WARNprovider:
name: aws
runtime: java21
vpc:
securityGroupIds:
- !Ref LambdaSecurityGroup
subnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
resources:
Resources:
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Lambda Security Group
VpcId: !Ref VPC
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.1.0/24
AvailabilityZone: !Select [0, !GetAZs '']
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VPC
CidrBlock: 10.0.2.0/24
AvailabilityZone: !Select [1, !GetAZs '']plugins:
- serverless-domain-manager
custom:
customDomain:
domainName: api.example.com
stage: ${self:provider.stage}
createRoute53Record: true
certificateName: '*.example.com'
endpointType: 'regional'
securityPolicy: tls_1_2AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Java Lambda API with SAM
Globals:
Function:
Timeout: 10
MemorySize: 512
Runtime: java21
Architectures:
- x86_64
Environment:
Variables:
JAVA_TOOL_OPTIONS: -XX:+TieredCompilation -XX:TieredStopAtLevel=1
Tags:
Project: MyJavaApi
Parameters:
Stage:
Type: String
Default: dev
AllowedValues:
- dev
- staging
- prod
Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub '${AWS::StackName}-api'
CodeUri: build/libs/function.jar
Handler: com.example.Handler
Description: Java Lambda API Handler
AutoPublishAlias: live
DeploymentPreference:
Type: Canary10Percent5Minutes
Alarms:
- !Ref ErrorsAlarm
Events:
ApiEvent:
Type: Api
Properties:
Path: /{proxy+}
Method: ANY
RestApiId: !Ref ApiGateway
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref UsersTable
- Statement:
- Effect: Allow
Action:
- cloudwatch:PutMetricData
Resource: '*'
ApiGateway:
Type: AWS::Serverless::Api
Properties:
Name: !Sub '${AWS::StackName}-api'
StageName: !Ref Stage
Cors:
AllowMethods: "'GET,POST,PUT,DELETE,OPTIONS'"
AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
AllowOrigin: "'*'"
TracingEnabled: true
MethodSettings:
- ResourcePath: /*
HttpMethod: '*'
LoggingLevel: INFO
DataTraceEnabled: true
MetricsEnabled: true
UsersTable:
Type: AWS::DynamoDB::Table
Properties:
TableName: !Sub '${AWS::StackName}-users'
BillingMode: PAY_PER_REQUEST
AttributeDefinitions:
- AttributeName: id
AttributeType: S
KeySchema:
- AttributeName: id
KeyType: HASH
PointInTimeRecoverySpecification:
PointInTimeRecoveryEnabled: !If [IsProd, true, false]
ErrorsAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub '${AWS::StackName}-errors'
MetricName: Errors
Namespace: AWS/Lambda
Statistic: Sum
Period: 60
EvaluationPeriods: 1
Threshold: 1
ComparisonOperator: GreaterThanOrEqualToThreshold
Dimensions:
- Name: FunctionName
Value: !Ref ApiFunction
Conditions:
IsProd: !Equals [!Ref Stage, prod]
Outputs:
ApiUrl:
Description: API Gateway URL
Value: !Sub 'https://${ApiGateway}.execute-api.${AWS::Region}.amazonaws.com/${Stage}/'
FunctionArn:
Description: Lambda Function ARN
Value: !GetAtt ApiFunction.Arn
Export:
Name: !Sub '${AWS::StackName}-function-arn'Resources:
# Lambda Layer for common dependencies
DependenciesLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: java-dependencies
Description: Common Java dependencies
ContentUri: build/layers/dependencies/
CompatibleRuntimes:
- java21
RetentionPolicy: Retain
ApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/function.jar
Handler: com.example.Handler
Layers:
- !Ref DependenciesLayer
Environment:
Variables:
JAVA_TOOL_OPTIONS: -cp /opt/java/lib/*:lib/*# samconfig.toml
version = 0.1
[default]
[default.global.parameters]
stack_name = java-lambda-api
[default.build.parameters]
cached = true
parallel = true
[default.validate.parameters]
lint = true
[default.deploy.parameters]
capabilities = CAPABILITY_IAM
confirm_changeset = true
resolve_s3 = true
s3_prefix = java-lambda-api
[default.local_start_api.parameters]
warm_containers = EAGER
[default.local_invoke.parameters]
parameter_overrides = "Stage=local"# .github/workflows/deploy.yml
name: Build and Deploy
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
JAVA_VERSION: '21'
AWS_REGION: us-east-1
jobs:
test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: 'temurin'
cache: gradle
- name: Run tests
run: ./gradlew test
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
files: build/reports/jacoco/test/jacocoTestReport.xml
build:
needs: test
runs-on: ubuntu-latest
outputs:
artifact-path: ${{ steps.build.outputs.artifact-path }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: 'temurin'
cache: gradle
- name: Build JAR
id: build
run: |
./gradlew shadowJar
echo "artifact-path=build/libs/$(ls build/libs/*.jar | head -n 1)" >> $GITHUB_OUTPUT
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: lambda-jar
path: build/libs/*.jar
retention-days: 1
deploy-dev:
needs: build
runs-on: ubuntu-latest
environment: development
if: github.ref == 'refs/heads/develop'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: lambda-jar
path: build/libs/
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Deploy with Serverless
run: |
npm install -g serverless
serverless deploy --stage dev --region $AWS_REGION
deploy-staging:
needs: build
runs-on: ubuntu-latest
environment: staging
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: lambda-jar
path: build/libs/
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Deploy with SAM
run: |
sam build
sam deploy \
--stack-name java-api-staging \
--s3-bucket $DEPLOYMENT_BUCKET \
--region $AWS_REGION \
--capabilities CAPABILITY_IAM \
--parameter-overrides Stage=staging \
--no-confirm-changeset
deploy-production:
needs: deploy-staging
runs-on: ubuntu-latest
environment: production
if: github.ref == 'refs/heads/main'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download artifact
uses: actions/download-artifact@v4
with:
name: lambda-jar
path: build/libs/
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
- name: Deploy to Production
run: |
sam deploy \
--stack-name java-api-prod \
--s3-bucket $DEPLOYMENT_BUCKET \
--region $AWS_REGION \
--capabilities CAPABILITY_IAM \
--parameter-overrides Stage=prod \
--no-confirm-changeset# .github/workflows/sam-pipeline.yml
name: SAM Pipeline
on:
push:
branches: [main]
workflow_dispatch:
inputs:
environment:
description: 'Deployment environment'
required: true
default: 'staging'
type: choice
options:
- staging
- production
jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- uses: aws-actions/setup-sam@v2
with:
use-installer: true
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_DEPLOY_ROLE_ARN }}
aws-region: us-east-1
- uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
cache: gradle
- name: Build application
run: ./gradlew shadowJar
- name: SAM Build
run: sam build
- name: SAM Deploy
run: |
sam deploy \
--stack-name java-api-${{ github.event.inputs.environment || 'staging' }} \
--resolve-s3 \
--capabilities CAPABILITY_IAM \
--parameter-overrides Stage=${{ github.event.inputs.environment || 'staging' }} \
--no-confirm-changeset \
--no-fail-on-empty-changesetfunctions:
api:
handler: com.example.Handler
provisionedConcurrency: 10
events:
- http:
path: /{proxy+}
method: ANY
# Scheduled scaling (optional)
provisionedConcurrencyScalers:
- schedule: cron(0 9 * * ? *)
value: 20
- schedule: cron(0 18 * * ? *)
value: 5Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/function.jar
Handler: com.example.Handler
AutoPublishAlias: live
ProvisionedConcurrencyConfig:
ProvisionedConcurrentExecutions: 10
# Scheduled scaling with Application Auto Scaling
ScalableTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
Properties:
MaxCapacity: 50
MinCapacity: 5
ResourceId: !Sub 'function:${ApiFunction}:live'
RoleARN: !Sub 'arn:aws:iam::${AWS::AccountId}:role/aws-service-role/lambda.application-autoscaling.amazonaws.com/AWSServiceRoleForApplicationAutoScaling_LambdaConcurrency'
ScalableDimension: lambda:function:ProvisionedConcurrency
ServiceNamespace: lambda
ScalingPolicy:
Type: AWS::ApplicationAutoScaling::ScalingPolicy
Properties:
PolicyName: lambda-provisioned-concurrency-policy
PolicyType: TargetTrackingScaling
ScalingTargetId: !Ref ScalableTarget
TargetTrackingScalingPolicyConfiguration:
TargetValue: 0.7
PredefinedMetricSpecification:
PredefinedMetricType: LambdaProvisionedConcurrencyUtilizationResources:
BusinessHoursScaleUp:
Type: AWS::AutoScaling::ScheduledAction
Properties:
AutoScalingGroupName: !Ref ScalableTarget
MinSize: 20
MaxSize: 50
Recurrence: 0 9 * * MON-FRI
TimeZone: America/New_York
BusinessHoursScaleDown:
Type: AWS::AutoScaling::ScheduledAction
Properties:
AutoScalingGroupName: !Ref ScalableTarget
MinSize: 5
MaxSize: 50
Recurrence: 0 18 * * MON-FRI
TimeZone: America/New_YorkResources:
HighErrorRateAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub '${AWS::StackName}-high-error-rate'
AlarmDescription: Error rate exceeds 1%
MetricName: Errors
Namespace: AWS/Lambda
Statistic: Sum
Period: 300
EvaluationPeriods: 2
Threshold: 10
ComparisonOperator: GreaterThanThreshold
TreatMissingData: notBreaching
Dimensions:
- Name: FunctionName
Value: !Ref ApiFunction
HighDurationAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub '${AWS::StackName}-high-duration'
AlarmDescription: Average duration exceeds 5 seconds
MetricName: Duration
Namespace: AWS/Lambda
Statistic: Average
Period: 300
EvaluationPeriods: 2
Threshold: 5000
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: FunctionName
Value: !Ref ApiFunction
ThrottlingAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub '${AWS::StackName}-throttling'
MetricName: Throttles
Namespace: AWS/Lambda
Statistic: Sum
Period: 60
EvaluationPeriods: 1
Threshold: 1
ComparisonOperator: GreaterThanOrEqualToThreshold
Dimensions:
- Name: FunctionName
Value: !Ref ApiFunction// Emit custom metrics from Lambda
private void emitMetric(String name, double value, String unit) {
PutMetricDataRequest request = PutMetricDataRequest.builder()
.namespace("MyApplication")
.metricData(MetricDatum.builder()
.metricName(name)
.value(value)
.unit(unit)
.dimensions(
Dimension.builder().name("Function").value("ApiHandler").build(),
Dimension.builder().name("Stage").value(System.getenv("STAGE")).build()
)
.build())
.build();
cloudWatchClient.putMetricData(request);
}
// Usage
emitMetric("ProcessingTime", duration, StandardUnit.MILLISECONDS);
emitMetric("ItemsProcessed", count, StandardUnit.Count);Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
Tracing: Active
Environment:
Variables:
AWS_XRAY_CONTEXT_MISSING: LOG_ERROR// Add subsegments for detailed tracing
import com.amazonaws.xray.AWSXRay;
import com.amazonaws.xray.entities.Subsegment;
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent request, Context context) {
Subsegment subsegment = AWSXRay.beginSubsegment("ProcessRequest");
try {
// Business logic
subsegment.putAnnotation("userId", userId);
subsegment.putMetadata("request", Map.of("path", request.getPath()));
return processRequest(request);
} catch (Exception e) {
subsegment.addException(e);
throw e;
} finally {
AWSXRay.endSubsegment();
}
}-- Find cold starts
fields @timestamp, @message, @duration
| filter @message like /INIT_START/
| stats count() as cold_starts by bin(5m)
-- Average duration by stage
fields @duration, @memorySize
| filter @type = "REPORT"
| stats avg(@duration), max(@duration), min(@duration) by @memorySize
-- Error analysis
fields @timestamp, @message
| filter @message like /ERROR/
| stats count() as errors by bin(1h)
| sort by @timestamp desc
-- Performance by endpoint (requires custom logging)
fields @timestamp, @message
| parse @message "path: *, duration: *ms" as path, duration
| stats avg(duration), max(duration), count() by path
| sort by avg(duration) desc// build.gradle
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '8.1.1'
}
java {
sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_21
}
// Optimized build task for Lambda deployment packages
task buildZip(type: Zip) {
from compileJava
from processResources
into('lib') {
from configurations.runtimeClasspath
}
archiveFileName = "${project.name}-${project.version}.zip"
}
// Shadow JAR with minimized dependencies
shadowJar {
archiveClassifier = ''
mergeServiceFiles()
// Exclude unnecessary files to reduce JAR size
exclude 'META-INF/*.SF'
exclude 'META-INF/*.DSA'
exclude 'META-INF/*.RSA'
exclude 'META-INF/LICENSE*'
exclude 'META-INF/NOTICE*'
// Minimize to only include used classes
minimize()
}
dependencies {
// AWS SDK v2 - include only needed modules
implementation 'software.amazon.awssdk:dynamodb:2.25.0'
implementation 'software.amazon.awssdk:s3:2.25.0'
implementation 'software.amazon.awssdk:lambda:2.25.0'
// Avoid entire AWS SDK - do NOT use:
// implementation 'software.amazon.awssdk:aws-sdk-java:2.25.0'
// Prefer lightweight DI frameworks over Spring
implementation 'com.google.dagger:dagger:2.51'
annotationProcessor 'com.google.dagger:dagger-compiler:2.51'
// Or use Guice if needed
// implementation 'com.google.inject:guice:7.0.0'
// Lambda runtime
implementation 'com.amazonaws:aws-lambda-java-core:1.2.3'
implementation 'com.amazonaws:aws-lambda-java-events:3.11.4'
// Logging (lightweight)
implementation 'org.slf4j:slf4j-simple:2.0.12'
}<!-- pom.xml -->
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>21</source>
<target>21</target>
</configuration>
</plugin>
<!-- Maven Shade Plugin for creating uber JAR -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>META-INF/LICENSE*</exclude>
<exclude>META-INF/NOTICE*</exclude>
</excludes>
</filter>
</filters>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<!-- AWS SDK v2 - selective modules only -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>dynamodb</artifactId>
<version>2.25.0</version>
</dependency>
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.25.0</version>
</dependency>
<!-- Lambda runtime -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.2.3</version>
</dependency>
</dependencies>// Separate Lambda handler from core business logic
public class LambdaHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
private final OrderService orderService;
// Constructor for Lambda runtime (with dependency injection)
public LambdaHandler() {
this.orderService = DaggerOrderComponent.create().orderService();
}
// Constructor for testing
public LambdaHandler(OrderService orderService) {
this.orderService = orderService;
}
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent request, Context context) {
// Delegate to core logic
return orderService.processOrder(request);
}
}
// Core business logic separate from Lambda infrastructure
public class OrderService {
private final OrderRepository repository;
private final NotificationService notificationService;
@Inject
public OrderService(OrderRepository repository, NotificationService notificationService) {
this.repository = repository;
this.notificationService = notificationService;
}
public APIGatewayProxyResponseEvent processOrder(APIGatewayProxyRequestEvent request) {
// Business logic here - can be tested independently
}
}# SAM template with Lambda Layers
Resources:
# Shared dependencies layer
DependenciesLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: java-common-dependencies
Description: Common Java dependencies for Lambda functions
ContentUri: build/layers/dependencies/
CompatibleRuntimes:
- java21
RetentionPolicy: Retain
# Function using the layer
ApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/function.jar
Handler: com.example.Handler
Layers:
- !Ref DependenciesLayer
Environment:
Variables:
JAVA_TOOL_OPTIONS: -cp /opt/java/lib/*:lib/*// build.gradle - Create layer structure
task buildLayer(type: Copy) {
from configurations.runtimeClasspath
into "build/layers/dependencies/java/lib"
// Exclude AWS SDK provided by Lambda runtime
exclude 'aws-lambda-java-core*.jar'
exclude 'aws-lambda-java-events*.jar'
}
// Build minimal function JAR (business logic only)
task buildFunctionJar(type: Jar) {
from sourceSets.main.output
exclude '**/lib/**'
archiveFileName = "function.jar"
}// Exclude unnecessary dependencies
dependencies {
implementation('com.fasterxml.jackson.core:jackson-databind:2.16.0') {
// Exclude unused Jackson modules
exclude group: 'com.fasterxml.jackson.module'
}
// Use ProGuard for aggressive optimization (advanced)
// buildscript { dependencies { classpath 'com.guardsquare:proguard-gradle:7.4.0' } }
}
// Gradle configuration for minimal JAR
jar {
enabled = false // Disable standard JAR, use shadow only
}
shadowJar {
// Remove unused classes
minimize {
exclude(dependency('org.slf4j:.*:.*'))
}
// Relocate packages to avoid conflicts
relocate 'com.fasterxml.jackson', 'shaded.com.fasterxml.jackson'
}<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/layers/java/lib</outputDirectory>
<includeScope>runtime</includeScope>
<excludeArtifactIds>aws-lambda-java-core,aws-lambda-java-events</excludeArtifactIds>
</configuration>
</execution>
</executions>
</plugin>Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
Runtime: java21
Environment:
Variables:
# Optimized JVM flags for Lambda cold starts
JAVA_TOOL_OPTIONS: >
-XX:+TieredCompilation
-XX:TieredStopAtLevel=1
-XX:+UseSerialGC
-XX:MaxRAMPercentage=75.0
-XX:InitialRAMPercentage=50.0JVM Option Explanations:
| Option | Purpose | Impact |
|---|---|---|
-XX:+TieredCompilation | Enable tiered compilation | Faster startup |
-XX:TieredStopAtLevel=1 | Stop at C1 compiler only | Reduced compilation time |
-XX:+UseSerialGC | Use single-threaded GC | Lower memory overhead |
-XX:MaxRAMPercentage=75.0 | Limit heap to 75% of container memory | Prevent OOM |
# Memory allocation vs vCPU allocation
# 1769MB = 1 vCPU (linear scaling below this threshold)
Resources:
LowMemoryFunction:
Type: AWS::Serverless::Function
Properties:
MemorySize: 512
# Suitable for: Simple CRUD, low throughput
BalancedFunction:
Type: AWS::Serverless::Function
Properties:
MemorySize: 1024
# Good balance of performance and cost
HighPerformanceFunction:
Type: AWS::Serverless::Function
Properties:
MemorySize: 1769
# 1 full vCPU - optimal for CPU-intensive tasks
MaximumPerformanceFunction:
Type: AWS::Serverless::Function
Properties:
MemorySize: 3008
# 2 vCPUs - for compute-intensive operationspublic class OptimizedHandler implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
// Initialize heavy resources statically (during init phase)
private static final DynamoDbClient dynamoDbClient = DynamoDbClient.builder()
.httpClientBuilder(UrlConnectionHttpClient.builder()) // Lightweight HTTP client
.build();
private static final ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule());
// Initialize during first invocation if needed
private final OrderRepository orderRepository;
public OptimizedHandler() {
// This runs during init phase (not counted in billing)
this.orderRepository = new OrderRepository(dynamoDbClient);
}
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent request, Context context) {
// Handler execution - reuse initialized resources
return processRequest(request);
}
}// HTTP client configuration for Lambda
public class HttpClientConfig {
public static HttpClient createOptimizedClient() {
return HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(5))
.version(HttpClient.Version.HTTP_2)
.build();
}
}
// Database connection pooling (if using RDS Proxy or direct connections)
public class DatabaseConfig {
public static HikariDataSource createDataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl(System.getenv("DB_URL"));
config.setUsername(System.getenv("DB_USER"));
config.setPassword(System.getenv("DB_PASSWORD"));
// Lambda-optimized pool settings
config.setMaximumPoolSize(2); // Keep minimal for Lambda
config.setMinimumIdle(0); // Don't maintain idle connections
config.setIdleTimeout(10000); // 10 second idle timeout
config.setConnectionTimeout(5000);
config.setMaxLifetime(300000); // 5 minutes max lifetime
return new HikariDataSource(config);
}
}AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/function.jar
Handler: com.example.Handler
Runtime: java21
AutoPublishAlias: live # Required for traffic shifting
# Deployment preferences with automatic rollback
DeploymentPreference:
Type: Canary10Percent5Minutes
Alarms:
- !Ref ErrorRateAlarm
- !Ref LatencyAlarm
Hooks:
PreTraffic: !Ref PreTrafficHookFunction
PostTraffic: !Ref PostTrafficHookFunction
# Pre-traffic hook for validation
PreTrafficHookFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/hooks.jar
Handler: com.example.hooks.PreTrafficHook
Runtime: java21
Policies:
- Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- codedeploy:PutLifecycleEventHookExecutionStatus
Resource: '*'
# Post-traffic hook for verification
PostTrafficHookFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/hooks.jar
Handler: com.example.hooks.PostTrafficHook
Runtime: java21
Policies:
- Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- codedeploy:PutLifecycleEventHookExecutionStatus
Resource: '*'
# Alarms for automatic rollback triggers
ErrorRateAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub '${AWS::StackName}-error-rate'
MetricName: Errors
Namespace: AWS/Lambda
Statistic: Sum
Period: 60
EvaluationPeriods: 2
Threshold: 5
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: FunctionName
Value: !Ref ApiFunction
LatencyAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: !Sub '${AWS::StackName}-latency'
MetricName: Duration
Namespace: AWS/Lambda
Statistic: Average
Period: 60
EvaluationPeriods: 2
Threshold: 3000
ComparisonOperator: GreaterThanThreshold# Canary deployments - shift traffic gradually
DeploymentPreference:
Type: Canary10Percent5Minutes # 10% for 5 minutes, then 100%
# Other options:
# - Canary10Percent30Minutes
# - Canary10Percent5Minutes
# - Canary10Percent10Minutes
# - Canary10Percent15Minutes
# Linear deployments - shift traffic in increments
DeploymentPreference:
Type: Linear10PercentEvery1Minute # 10% per minute until 100%
# Other options:
# - Linear10PercentEvery2Minutes
# - Linear10PercentEvery3Minutes
# - Linear10PercentEvery10Minutes
# All-at-once (no rollback capability)
DeploymentPreference:
Type: AllAtOnce// Pre-traffic hook for smoke tests
public class PreTrafficHook implements RequestHandler<Map<String, Object>, String> {
private final CodeDeployClient codeDeployClient;
private final HttpClient httpClient;
public PreTrafficHook() {
this.codeDeployClient = CodeDeployClient.create();
this.httpClient = HttpClient.newHttpClient();
}
@Override
public String handleRequest(Map<String, Object> event, Context context) {
String deploymentId = (String) event.get("DeploymentId");
String lifecycleEventHookExecutionId = (String) event.get("LifecycleEventHookExecutionId");
try {
// Run smoke tests against the new version
boolean testsPassed = runSmokeTests();
// Report status to CodeDeploy
PutLifecycleEventHookExecutionStatusRequest statusRequest =
PutLifecycleEventHookExecutionStatusRequest.builder()
.deploymentId(deploymentId)
.lifecycleEventHookExecutionId(lifecycleEventHookExecutionId)
.status(testsPassed ? LifecycleEventStatus.SUCCEEDED : LifecycleEventStatus.FAILED)
.build();
codeDeployClient.putLifecycleEventHookExecutionStatus(statusRequest);
return testsPassed ? "Success" : "Failure";
} catch (Exception e) {
context.getLogger().log("Pre-traffic hook failed: " + e.getMessage());
// Report failure to trigger rollback
codeDeployClient.putLifecycleEventHookExecutionStatus(
PutLifecycleEventHookExecutionStatusRequest.builder()
.deploymentId(deploymentId)
.lifecycleEventHookExecutionId(lifecycleEventHookExecutionId)
.status(LifecycleEventStatus.FAILED)
.build()
);
throw new RuntimeException(e);
}
}
private boolean runSmokeTests() {
// Implement smoke tests (health check, basic functionality)
return true;
}
}Resources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/function.jar
Handler: com.example.Handler
Policies:
# Use managed policies for common patterns
- DynamoDBCrudPolicy:
TableName: !Ref UsersTable
# Custom least-privilege policy
- Statement:
- Effect: Allow
Action:
- s3:GetObject
- s3:PutObject
Resource:
- !Sub 'arn:aws:s3:::${BucketName}/uploads/*'
Condition:
StringEquals:
s3:x-amz-acl: bucket-owner-full-control
# Explicit deny for sensitive operations
- Effect: Deny
Action:
- s3:DeleteBucket
- dynamodb:DeleteTable
Resource: '*'Resources:
VpcFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/function.jar
Handler: com.example.Handler
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSecurityGroup
SubnetIds:
- !Ref PrivateSubnet1
- !Ref PrivateSubnet2
# VPC functions require NAT Gateway for internet access
# or VPC endpoints for AWS services
# Security group with minimal access
LambdaSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Lambda security group
VpcId: !Ref VPC
SecurityGroupEgress:
- IpProtocol: tcp
FromPort: 443
ToPort: 443
CidrIp: 0.0.0.0/0
Description: HTTPS to AWS services
- IpProtocol: tcp
FromPort: 5432
ToPort: 5432
DestinationSecurityGroupId: !Ref RdsSecurityGroup
Description: PostgreSQL to RDS
# VPC Endpoints for AWS services (avoid NAT Gateway costs)
S3VpcEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref VPC
ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3'
VpcEndpointType: Gateway
RouteTableIds:
- !Ref PrivateRouteTable
DynamoDbVpcEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
VpcId: !Ref VPC
ServiceName: !Sub 'com.amazonaws.${AWS::Region}.dynamodb'
VpcEndpointType: Gateway
RouteTableIds:
- !Ref PrivateRouteTableResources:
SecureFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/function.jar
Handler: com.example.Handler
Environment:
Variables:
# Reference secrets by ARN (not value)
DB_SECRET_ARN: !Ref DatabaseSecret
API_KEY_PARAM: !Ref ApiKeyParameter
Policies:
- Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource: !Ref DatabaseSecret
- Effect: Allow
Action:
- ssm:GetParameter
Resource: !Ref ApiKeyParameter
# Secrets Manager for database credentials
DatabaseSecret:
Type: AWS::SecretsManager::Secret
Properties:
Name: !Sub '/${AWS::StackName}/database-credentials'
Description: RDS database credentials
GenerateSecretString:
SecretStringTemplate: '{"username": "dbadmin"}'
GenerateStringKey: password
PasswordLength: 32
ExcludeCharacters: '"@/\\'
KmsKeyId: !Ref SecretsKmsKey
# SSM Parameter Store for configuration
ApiKeyParameter:
Type: AWS::SSM::Parameter
Properties:
Name: !Sub '/${AWS::StackName}/api-key'
Type: SecureString
Value: placeholder-replace-manually
Description: External API key
Tier: Standard
# KMS key for encryption
SecretsKmsKey:
Type: AWS::KMS::Key
Properties:
Description: KMS key for Lambda secrets
EnableKeyRotation: true
KeyPolicy:
Version: '2012-10-17'
Statement:
- Sid: Enable IAM User Permissions
Effect: Allow
Principal:
AWS: !Sub 'arn:aws:iam::${AWS::AccountId}:root'
Action: 'kms:*'
Resource: '*'// Retrieve secrets in Lambda with caching
public class SecretCache {
private final SecretsManagerClient secretsClient;
private final Map<String, String> cache = new ConcurrentHashMap<>();
private final long cacheTtlMs = 300000; // 5 minutes
public String getSecret(String secretArn) {
return cache.computeIfAbsent(secretArn, arn -> {
GetSecretValueRequest request = GetSecretValueRequest.builder()
.secretId(arn)
.build();
GetSecretValueResponse response = secretsClient.getSecretValue(request);
return response.secretString();
});
}
// Parse JSON secrets
public DatabaseCredentials getDatabaseCredentials(String secretArn) {
String secretString = getSecret(secretArn);
return new ObjectMapper().readValue(secretString, DatabaseCredentials.class);
}
}Resources:
InternalFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/function.jar
Handler: com.example.Handler
# Explicit resource policy for cross-account or service access
FunctionResourcePolicy:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref InternalFunction
Action: lambda:InvokeFunction
Principal: apigateway.amazonaws.com
SourceArn: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${ApiGateway}/*'
# Service-specific invocation permission
S3InvokePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref S3ProcessorFunction
Action: lambda:InvokeFunction
Principal: s3.amazonaws.com
SourceArn: !Sub 'arn:aws:s3:::${BucketName}'
SourceAccount: !Ref AWS::AccountIdResources:
ArmFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: build/libs/function.jar
Handler: com.example.Handler
Runtime: java21
Architectures:
- arm64 # Graviton2 - up to 34% better price-performance
# Build configuration for ARM64
# Gradle: No changes needed - Java bytecode is architecture-independent
# But native dependencies must be ARM64 compatible// build.gradle - Multi-architecture build support
plugins {
id 'java'
}
dependencies {
// AWS SDK CRT client for ARM64 optimization
implementation 'software.amazon.awssdk:aws-crt-client:2.25.0'
// Ensure all native dependencies have ARM64 support
implementation 'io.netty:netty-transport-native-epoll:4.1.107.Final:linux-aarch_64'
}# Find optimal memory/price ratio using AWS Lambda Power Tuning
Resources:
TunedFunction:
Type: AWS::Serverless::Function
Properties:
MemorySize: 1769 # Sweet spot: 1 vCPU, good performance/cost ratio
# Test different values: 512, 1024, 1769, 3008
# Use Lambda Power Tuning tool to find optimal setting
# https://github.com/alexcasalboni/aws-lambda-power-tuning# Cost comparison: On-demand vs Provisioned Concurrency
# On-demand (pay per invocation):
# - $0.20 per 1M requests
# - $0.0000166667 per GB-second
# - Cold starts on scale-up
# Provisioned Concurrency (predictable performance):
# - $0.20 per 1M requests (same)
# - $0.000004646 per GB-second (lower compute cost)
# - $0.000004646 per GB-second provisioned (base cost)
Resources:
# Use for predictable, latency-sensitive workloads
HighTrafficFunction:
Type: AWS::Serverless::Function
Properties:
MemorySize: 1024
AutoPublishAlias: live
ProvisionedConcurrencyConfig:
ProvisionedConcurrentExecutions: 10
# Scheduled scaling to optimize cost
ScalableTarget:
Type: AWS::ApplicationAutoScaling::ScalableTarget
Properties:
MinCapacity: 2 # Minimum during off-hours
MaxCapacity: 50 # Maximum during peak# Share common dependencies across functions to reduce deployment size
Resources:
SharedLayer:
Type: AWS::Serverless::LayerVersion
Properties:
LayerName: shared-java-deps
ContentUri: layers/shared/
CompatibleRuntimes:
- java21
FunctionA:
Type: AWS::Serverless::Function
Properties:
CodeUri: function-a/build/distributions/function-a.zip
Handler: com.example.FunctionAHandler
Layers:
- !Ref SharedLayer
# Smaller deployment package = faster cold starts
FunctionB:
Type: AWS::Serverless::Function
Properties:
CodeUri: function-b/build/distributions/function-b.zip
Handler: com.example.FunctionBHandler
Layers:
- !Ref SharedLayer
# Reuses same layer, no duplication| Feature | SAM | Serverless Framework |
|---|---|---|
| Native AWS | Yes - AWS-maintained | No - Third-party |
| Build system | Gradle/Maven native | Plugin-based (Gradle plugin available) |
| Local testing | SAM CLI (local invoke, local API) | serverless-offline |
| Java support | Native first-class | Via plugins |
| Deployment | CloudFormation-based | CloudFormation-based |
| Syntax | YAML/JSON | YAML |
| CI/CD integration | Native GitHub Actions, CodePipeline | Extensive plugin ecosystem |
| Rollback | Built-in CodeDeploy integration | Manual or custom scripts |
| IDE support | AWS Toolkit (IntelliJ, VS Code) | Limited |
| Debugging | Local debugging with breakpoints | Limited |
| Velocity macros | Supported | Not applicable |
# Deploy to specific stage
serverless deploy --stage prod --region us-east-1
# Deploy single function
serverless deploy function -f api
# Package without deploying
serverless package --stage prod
# View logs
serverless logs -f api --tail
# Remove stack
serverless remove --stage prod# Build
sam build
# Local test
sam local invoke ApiFunction -e events/test.json
sam local start-api
# Deploy
sam deploy --guided
sam deploy --no-confirm-changeset
# View logs
sam logs -n ApiFunction --tail
# Delete stack
sam delete --stack-name my-stackprovider:
environment:
DATABASE_URL: ${ssm:/my-app/${self:provider.stage}/database-url}
API_KEY: ${ssm:/my-app/${self:provider.stage}/api-key~true} # SecureStringResources:
ApiFunction:
Type: AWS::Serverless::Function
Properties:
Environment:
Variables:
DB_SECRET_ARN: !Ref DatabaseSecret
Policies:
- Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource: !Ref DatabaseSecret
DatabaseSecret:
Type: AWS::SecretsManager::Secret
Properties:
Name: !Sub '/${AWS::StackName}/database-credentials'
GenerateSecretString:
SecretStringTemplate: '{"username": "admin"}'
GenerateStringKey: password
PasswordLength: 16// Retrieve secret in Lambda
private String getSecret(String secretName) {
GetSecretValueRequest request = GetSecretValueRequest.builder()
.secretId(secretName)
.build();
GetSecretValueResponse response = secretsManager.getSecretValue(request);
return response.secretString();
}plugins
developer-kit-ai
skills
chunking-strategy
prompt-engineering
developer-kit-aws
skills
aws
aws-cli-beast
aws-cost-optimization
aws-drawio-architecture-diagrams
aws-sam-bootstrap
aws-cloudformation
aws-cloudformation-auto-scaling
references
aws-cloudformation-bedrock
references
aws-cloudformation-cloudfront
references
aws-cloudformation-cloudwatch
references
aws-cloudformation-dynamodb
references
aws-cloudformation-ec2
aws-cloudformation-ecs
references
aws-cloudformation-elasticache
aws-cloudformation-iam
references
aws-cloudformation-lambda
references
aws-cloudformation-rds
aws-cloudformation-s3
references
aws-cloudformation-security
references
aws-cloudformation-task-ecs-deploy-gh
aws-cloudformation-vpc
developer-kit-core
skills
developer-kit-java
skills
aws-lambda-java-integration
aws-rds-spring-boot-integration
aws-sdk-java-v2-bedrock
aws-sdk-java-v2-core
aws-sdk-java-v2-dynamodb
aws-sdk-java-v2-kms
aws-sdk-java-v2-lambda
aws-sdk-java-v2-messaging
aws-sdk-java-v2-rds
aws-sdk-java-v2-s3
aws-sdk-java-v2-secrets-manager
graalvm-native-image
langchain4j
langchain4j-mcp-server-patterns
langchain4j-ai-services-patterns
references
langchain4j-mcp-server-patterns
references
langchain4j-rag-implementation-patterns
references
langchain4j-spring-boot-integration
langchain4j-testing-strategies
langchain4j-tool-function-calling-patterns
langchain4j-vector-stores-configuration
references
qdrant
references
spring-ai-mcp-server-patterns
references
spring-boot-actuator
spring-boot-cache
spring-boot-crud-patterns
spring-boot-dependency-injection
spring-boot-event-driven-patterns
spring-boot-openapi-documentation
spring-boot-project-creator
spring-boot-resilience4j
spring-boot-rest-api-standards
spring-boot-saga-pattern
spring-boot-security-jwt
assets
references
scripts
spring-boot-test-patterns
spring-data-jpa
references
spring-data-neo4j
references
unit-test-application-events
unit-test-bean-validation
unit-test-boundary-conditions
unit-test-caching
unit-test-config-properties
unit-test-controller-layer
unit-test-exception-handler
unit-test-json-serialization
unit-test-mapper-converter
unit-test-parameterized
unit-test-scheduled-async
unit-test-service-layer
unit-test-utility-methods
unit-test-wiremock-rest-api
developer-kit-php
skills
aws-lambda-php-integration
developer-kit-python
skills
aws-lambda-python-integration
developer-kit-tools
developer-kit-typescript
skills
aws-lambda-typescript-integration
better-auth
drizzle-orm-patterns
dynamodb-toolbox-patterns
references
nestjs
nestjs-best-practices
nestjs-code-review
nestjs-drizzle-crud-generator
scripts
nextjs-app-router
nextjs-authentication
nextjs-code-review
nextjs-data-fetching
references
nextjs-deployment
nextjs-performance
nx-monorepo
react-code-review
react-patterns
references
shadcn-ui
tailwind-css-patterns
references
tailwind-design-system
references
turborepo-monorepo
typescript-docs
typescript-security-review
zod-validation-utilities