CtrlK
BlogDocsLog inGet started
Tessl Logo

giuseppe-trisciuoglio/developer-kit

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

Quality

82%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Risky

Do not use without reviewing

Validation failed for skills in this tile
One or more skills have errors that need to be fixed before they can move to Implementation and Discovery review.
Overview
Quality
Evals
Security
Files

serverless-deployment.mdplugins/developer-kit-java/skills/aws-lambda-java-integration/references/

Serverless Deployment Reference

Complete guide for deploying Java Lambda functions with Serverless Framework, AWS SAM, and CI/CD pipelines.

Table of Contents

  1. Serverless Framework
  2. AWS SAM
  3. CI/CD Pipeline
  4. Provisioned Concurrency
  5. Monitoring
  6. Build Optimization
  7. Package Optimization
  8. Performance Tuning
  9. Rollback Strategy
  10. Security Best Practices
  11. Cost Optimization
  12. SAM vs Serverless Framework

Serverless Framework

Basic Configuration

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}

Multi-Stage Configuration

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: WARN

VPC Configuration

provider:
  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 '']

Custom Domain

plugins:
  - serverless-domain-manager

custom:
  customDomain:
    domainName: api.example.com
    stage: ${self:provider.stage}
    createRoute53Record: true
    certificateName: '*.example.com'
    endpointType: 'regional'
    securityPolicy: tls_1_2

AWS SAM

Basic Template

AWSTemplateFormatVersion: '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'

SAM with Layers

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/*

SAM Local Testing

# 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"

CI/CD Pipeline

GitHub Actions - Full Pipeline

# .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 Actions - SAM Only

# .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-changeset

Provisioned Concurrency

Serverless Framework

functions:
  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: 5

SAM Template

Resources:
  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: LambdaProvisionedConcurrencyUtilization

Auto Scaling Based on Schedule

Resources:
  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_York

Monitoring

CloudWatch Alarms

Resources:
  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

Custom Metrics

// 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);

X-Ray Tracing

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();
    }
}

CloudWatch Logs Insights Queries

-- 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 Optimization

Gradle Configuration

// 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'
}

Maven Configuration

<!-- 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>

Handler Separation Pattern

// 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
    }
}

Package Optimization

Lambda Layers for Java Dependencies

# 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"
}

JAR Size Reduction Techniques

// 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'
}

Maven Dependency Copy for Layer

<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>

Performance Tuning

JVM Options for Lambda

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.0

JVM Option Explanations:

OptionPurposeImpact
-XX:+TieredCompilationEnable tiered compilationFaster startup
-XX:TieredStopAtLevel=1Stop at C1 compiler onlyReduced compilation time
-XX:+UseSerialGCUse single-threaded GCLower memory overhead
-XX:MaxRAMPercentage=75.0Limit heap to 75% of container memoryPrevent OOM

Memory Configuration Guidance

# 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 operations

Cold Start Optimization

public 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);
    }
}

Connection Pool Settings

// 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);
    }
}

Rollback Strategy

AWS SAM with CodeDeploy Integration

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

Deployment Types

# 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/Post Traffic Hook Implementation

// 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;
    }
}

Security Best Practices

IAM Least Privilege

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: '*'

VPC Configuration

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 PrivateRouteTable

Secrets Manager and SSM Parameter Store

Resources:
  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);
    }
}

Resource-Based Policies

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::AccountId

Cost Optimization

Graviton2 (ARM64) Support

Resources:
  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'
}

Memory Size Tuning

# 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

Provisioned Concurrency Cost Analysis

# 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

Lambda Layers for Shared Dependencies

# 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

SAM vs Serverless Framework

FeatureSAMServerless Framework
Native AWSYes - AWS-maintainedNo - Third-party
Build systemGradle/Maven nativePlugin-based (Gradle plugin available)
Local testingSAM CLI (local invoke, local API)serverless-offline
Java supportNative first-classVia plugins
DeploymentCloudFormation-basedCloudFormation-based
SyntaxYAML/JSONYAML
CI/CD integrationNative GitHub Actions, CodePipelineExtensive plugin ecosystem
RollbackBuilt-in CodeDeploy integrationManual or custom scripts
IDE supportAWS Toolkit (IntelliJ, VS Code)Limited
DebuggingLocal debugging with breakpointsLimited
Velocity macrosSupportedNot applicable

When to Choose SAM

  • Native AWS tooling and support
  • Deep Java integration with build tools
  • Built-in safe deployments with rollback
  • Local testing with SAM CLI
  • AWS IDE toolkit integration

When to Choose Serverless Framework

  • Multi-cloud requirements (Azure, GCP)
  • Large plugin ecosystem needed
  • Team familiar with Node.js tooling
  • Complex event source configurations
  • Non-AWS resource management

Deployment Commands

Serverless

# 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

SAM

# 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-stack

Environment Variables Management

SSM Parameter Store

provider:
  environment:
    DATABASE_URL: ${ssm:/my-app/${self:provider.stage}/database-url}
    API_KEY: ${ssm:/my-app/${self:provider.stage}/api-key~true}  # SecureString

Secrets Manager

Resources:
  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-java

skills

README.md

tile.json