---
title: Parameters
description: Utility
---


The parameters utilities provide a way to retrieve parameter values from
[AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html), 
[AWS Secrets Manager](https://aws.amazon.com/secrets-manager/), [Amazon DynamoDB](https://aws.amazon.com/dynamodb/), 
or [AWS AppConfig](https://aws.amazon.com/systems-manager/features/appconfig/). 
 
## Key features

* Retrieve one or multiple parameters from an underlying provider in a standard way
* Cache parameter values for a given amount of time (defaults to 5 seconds)
* Transform parameter values from JSON or base 64 encoded strings
* GraalVM support

## Install
In order to provide lightweight dependencies, each parameters module is available as its own
package:

* **Secrets Manager** - `powertools-parameters-secrets`  
* **SSM Parameter Store** - `powertools-parameters-ssm`  
* **Amazon DynamoDB** -`powertools-parameters-dynamodb` 
* **AWS AppConfig** - `powertools-parameters-appconfig`

You can easily mix and match parameter providers within the same project for different needs.  

Note that you must provide the concrete parameters module you want to use below - see the TODOs!

=== "Maven"

    ```xml hl_lines="4-12 17 24 30-34"
    <dependencies>
        ...
        <dependency>
            <groupId>software.amazon.lambda</groupId>

             <!-- TODO! Provide the parameters module you want to use here -->
             <artifactId>powertools-parameters-secrets</artifactId>
             <artifactId>powertools-parameters-ssm</artifactId>
             <artifactId>powertools-parameters-dynamodb</artifactId>
             <artifactId>powertools-parameters-appconfig</artifactId>

             <version>{{ powertools.version }}</version>
        </dependency>
        ...
    </dependencies>
    ...
    <!-- configure the aspectj-maven-plugin to compile-time weave (CTW) the aws-lambda-powertools-java aspects into your project -->
    <!-- Note: This AspectJ configuration is not needed when using the provider classes directly (without annotations) -->
    <build>
        <plugins>
            ...
            <plugin>
                 <groupId>dev.aspectj</groupId>
                 <artifactId>aspectj-maven-plugin</artifactId>
                 <version>1.14</version>
                 <configuration>
                     <source>11</source> <!-- or higher -->
                     <target>11</target> <!-- or higher -->
                     <complianceLevel>11</complianceLevel> <!-- or higher -->
                     <aspectLibraries>
                         <!-- TODO! Provide an aspectLibrary for each of the parameters module(s) you want to use here -->
                         <aspectLibrary>
                             <groupId>software.amazon.lambda</groupId>
                             <artifactId>powertools-parameters-secrets</artifactId>
                         </aspectLibrary>
                     </aspectLibraries>
                 </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.aspectj</groupId>
                        <artifactId>aspectjtools</artifactId>
                        <!-- AspectJ compiler version, in sync with runtime -->
                        <version>1.9.22</version>
                    </dependency>
                </dependencies>
                 <executions>
                     <execution>
                         <goals>
                             <goal>compile</goal>
                         </goals>
                     </execution>
                 </executions>
            </plugin>
            ...
        </plugins>
    </build>
    ```

=== "Gradle"

    ```groovy hl_lines="3 11-13"
        plugins {
            id 'java'
            id 'io.freefair.aspectj.post-compile-weaving' version '8.1.0' // Not needed when using provider classes directly (without annotations)
        }
        
        repositories {
            mavenCentral()
        }
        
        dependencies {
            // TODO! Provide the parameters module you want to use here
            aspect 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}' // Not needed when using provider classes directly (without annotations)
            implementation 'software.amazon.lambda:powertools-parameters-secrets:{{ powertools.version }}' // Use this instead of 'aspect' when using provider classes directly
        }
        
        sourceCompatibility = 11 // or higher
        targetCompatibility = 11 // or higher
    ```

**IAM Permissions**

This utility requires additional permissions to work as expected. See the table below:

| Provider  | Function/Method                                                         | IAM Permission                                                            |
|-----------|-------------------------------------------------------------------------|---------------------------------------------------------------------------|
| SSM       | `SSMProvider.get(String)` `SSMProvider.get(String, Class)`              | `ssm:GetParameter`                                                        |
| SSM       | `SSMProvider.getMultiple(String)`                                       | `ssm:GetParametersByPath`                                                 |
| SSM       | If using `withDecryption(true)`                                         | You must add an additional permission `kms:Decrypt`                       |
| Secrets   | `SecretsProvider.get(String)` `SecretsProvider.get(String, Class)`      | `secretsmanager:GetSecretValue`                                           |
| DynamoDB  | `DynamoDBProvider.get(String)` `DynamoDBProvider.getMultiple(string)`   | `dynamodb:GetItem` `dynamoDB:Query`                                       |
| AppConfig | `AppConfigProvider.get(String)` `AppConfigProvider.getMultiple(string)` | `appconfig:StartConfigurationSession`, `appConfig:GetLatestConfiguration` |

## Retrieving Parameters
You can retrieve parameters using either annotations or provider classes directly:

- **Annotations** (e.g., `@SecretsParam`, `@SSMParam`) - Simpler syntax with field injection, but requires AspectJ configuration
- **Provider classes** (e.g., `SecretsProvider`, `SSMProvider`) - No AspectJ required, useful when you need to configure the underlying SDK client (e.g., different region or credentials), or prefer avoiding AspectJ setup

## Built-in provider classes

This section describes the built-in provider classes for each parameter store. For each provider, examples are shown for both the annotation-based approach and the provider class approach. In cases where a provider supports extra features, these will also be described.

### Secrets Manager

=== "@SecretsParam annotation"

    ```java hl_lines="8 9"
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;
    import software.amazon.lambda.powertools.parameters.secrets.SecretsParam;
    
    public class ParametersFunction implements RequestHandler<String, String> {

        // Annotation-style injection from secrets manager
        @SecretsParam(key = "/powertools-java/userpwd")
        String secretParam;

        public string handleRequest(String request, Context context) {
            // ... do something with the secretParam here
            return "something";
        }
    }
    ```

=== "SecretsProvider class"

    ```java hl_lines="12-15 19"
    import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
    
    import com.amazonaws.services.lambda.runtime.Context;
    import software.amazon.awssdk.services.secretsmanager.SecretsManagerClient;
    import software.amazon.lambda.powertools.parameters.secrets.SecretsProvider;
    import com.amazonaws.services.lambda.runtime.RequestHandler;

    public class RequestHandlerWithParams implements RequestHandler<String, String> {
    
        // Get an instance of the SecretsProvider. We can provide a custom client here if we want,
        // for instance to use a particular region.
        SecretsProvider secretsProvider = SecretsProvider
                .builder()
                .withClient(SecretsManagerClient.builder().build())
                .build();
    
        public String handleRequest(String input, Context context) {
            // Retrieve a single secret
            String value = secretsProvider.get("/my/secret");
    
            // ... do something with the secretParam here
            return "something";
        }
    }
    ```

### SSM Parameter Store

The AWS Systems Manager Parameter Store provider supports two additional arguments for the `get()` and `getMultiple()` methods:

| Option     | Default | Description |
|---------------|---------|-------------|
| **withDecryption()**   | `False` | Will automatically decrypt the parameter. |
| **recursive()** | `False`  | For `getMultiple()` only, will fetch all parameter values recursively based on a path prefix. |


=== "@SSMParam annotation"

    ```java hl_lines="8 9"
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;
    import software.amazon.lambda.powertools.parameters.ssm.SSMParam;

    public class ParametersFunction implements RequestHandler<String, String> {

        // Annotation-style injection from SSM Parameter Store
        @SSMParam(key = "/powertools-java/param")
        String ssmParam;

        public string handleRequest(String request, Context context) {
            return ssmParam; // Request handler simply returns our configuration value
        }
    }
    ```

=== "SSMProvider class"

    ```java hl_lines="12-15 19-20 22"
    import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
    
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;
    import software.amazon.awssdk.services.ssm.SsmClient;
    import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;

    public class RequestHandlerWithParams implements RequestHandler<String, String> {
    
        // Get an instance of the SSMProvider. We can provide a custom client here if we want,
        // for instance to use a particular region.
        SSMProvider ssmProvider = SSMProvider
                .builder()
                .withClient(SsmClient.builder().build())
                .build();
    
        public String handleRequest(String input, Context context) {
            // Retrieve a single param
            String value = ssmProvider
                    .get("/my/secret");
                    // We might instead want to retrieve multiple parameters at once, returning a Map of key/value pairs
                    // .getMultiple("/my/secret/path");

            // Return the result
            return value;
        }
    }
    ```

=== "Additional Options"

    ```java hl_lines="5 9 12"
    import software.amazon.lambda.powertools.parameters.ssm.SSMProvider;

    public class AppWithSSM implements RequestHandler<APIGatewayProxyRequestEvent, APIGatewayProxyResponseEvent> {
        // Get an instance of the SSM Provider
        SSMProvider ssmProvider = SSMProvider.builder().build();
    
        // Retrieve a single parameter and decrypt it
        String value = ssmProvider.withDecryption().get("/my/parameter");
    
        // Retrieve multiple parameters recursively from a path prefix
        Map<String, String> values = ssmProvider.recursive().getMultiple("/my/path/prefix");
    
    }
    ```

### DynamoDB

=== "@DynamoDbParam annotation"

    ```java hl_lines="8 9"
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;
    import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDBParam;

    public class ParametersFunction implements RequestHandler<String, String> {

        // Annotation-style injection from DynamoDB
        @DynamoDbParam(table = "my-test-tablename", key = "myKey")
        String ddbParam;

        public string handleRequest(String request, Context context) {
            return ddbParam;  // Request handler simply returns our configuration value
        }
    }
    ```

=== "DynamoDbProvider class"

    ```java hl_lines="12-15 19-20 22"
    import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
    
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;
    import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
    import software.amazon.lambda.powertools.parameters.dynamodb.DynamoDbProvider;

    public class RequestHandlerWithParams implements RequestHandler<String, String> {
    
        // Get an instance of the DynamoDbProvider. We can provide a custom client here if we want,
        // for instance to use a particular region.
        DynamoDbProvider ddbProvider = DynamoDbProvider
                .builder()
                .withClient(DynamoDbClient.builder().build())
                .build();
    
        public String handleRequest(String input, Context context) {
            // Retrieve a single param
            String value = ddbProvider
                    .get("/my/secret");
                    // We might instead want to retrieve multiple values at once, returning a Map of key/value pairs
                    // .getMultiple("my-partition-key-value");
    
            // Return the result
            return value;
        }
    }
    ```

### AppConfig

=== "@AppConfigParam annotation"

    ```java hl_lines="8 9"
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;
    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigParam;

    public class ParametersFunction implements RequestHandler<String, String> {
    
        // Annotation-style injection from AppConfig
        @AppConfigParam(application = "my-app", environment = "my-env", key = "myKey")
        String appConfigParam;

        public string handleRequest(String request, Context context) {
            return appConfigParam; // Request handler simply returns our configuration value
        }
    }
    ```

=== "AppConfigProvider class"

    ```java hl_lines="12-15 19-20"
    import static software.amazon.lambda.powertools.parameters.transform.Transformer.base64;
    
    import com.amazonaws.services.lambda.runtime.Context;
    import com.amazonaws.services.lambda.runtime.RequestHandler;
    import software.amazon.awssdk.services.appconfigdata.AppConfigDataClient;
    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;

    public class RequestHandlerWithParams implements RequestHandler<String, String> {
    
        // Get an instance of the AppConfigProvider. We can provide a custom client here if we want,
        // for instance to use a particular region.
        AppConfigProvider appConfigProvider = AppConfigProvider
                .builder()
                .withClient(AppConfigDataClient.builder().build())
                .build();
    
        public String handleRequest(String input, Context context) {
            // Retrieve a single param
            String value = appConfigProvider
                    .get("/my/secret");
    
            // Return the result
            return value;
        }
    }    
    ```

## Advanced configuration

### Caching
Each provider uses the `CacheManager` to cache parameter values. When a value is retrieved using from the provider, a 
custom cache duration can be provided using `withMaxAge(duration, unit)`. 

If this is not specified, the default value set on the `CacheManager` itself will be used. This default can be customized
by calling `setDefaultExpirationTime(duration, unit)` on the `CacheManager`.

=== "Customize Cache"

    ```java hl_lines="9 10 14 19 22-25"
    import java.time.Duration;
    import software.amazon.lambda.powertools.parameters.appconfig.AppConfigProvider;
    import software.amazon.lambda.powertools.parameters.cache.CacheManager;
    
    public class CustomizeCache {
        
        public void CustomizeCache() {
    
            CacheManager cacheManager = new CacheManager();
            cacheManager.setDefaultExpirationTime(Duration.ofSeconds(10));
    
            AppConfigProvider paramProvider = AppConfigProvider
                    .builder()
                    .withCacheManager(cacheManager)
                    .withClient(AppConfigDataClient.builder().build())
                    .build();
    
            // Will use the default specified above - 10 seconds 
            String myParam1 = paramProvider.get("myParam1");

            // Will override the default above 
            String myParam2 = paramProvider
                .withMaxAge(20, ChronoUnit.SECONDS)
                .get("myParam2"); 

            return myParam2;
        }
    }
    ```


### Transform values

Parameter values can be transformed using ```withTransformation(transformerClass)```.
Base64 and JSON transformations are provided. For more complex transformation, you need to specify how to deserialize.

!!! warning "`getMultiple()` does not support transformation and will return simple Strings."

=== "Base64 Transformation"
    ```java
       String value = provider
                        .withTransformation(Transformer.base64)
                        .get("/my/parameter/b64");
    ```

=== "Complex Transformation"

    ```java
       MyObj object = provider
                        .withTransformation(Transformer.json)
                        .get("/my/parameter/json", MyObj.class);
    ```



#### Create your own Transformer

You can write your own transformer, by implementing the `Transformer` interface and the `applyTransformation()` method.
For example, if you wish to deserialize XML into an object.

=== "XmlTransformer.java"

    ```java
    public class XmlTransformer<T> implements Transformer<T> {
    
        private final XmlMapper mapper = new XmlMapper();
    
        @Override
        public T applyTransformation(String value, Class<T> targetClass) throws TransformationException {
            try {
                return mapper.readValue(value, targetClass);
            } catch (IOException e) {
                throw new TransformationException(e);
            }
        }
    }
    ```

=== "Using XmlTransformer"

    ```java
        MyObj object = provider
                            .withTransformation(XmlTransformer.class)
                            .get("/my/parameter/xml", MyObj.class);
    ```

### Fluent API

To simplify the use of the library, you can chain all method calls before a get.

=== "Fluent API call"

    ```java
        ssmProvider
          .withMaxAge(1, MINUTES)         // will set the cache TTL for this value at 1 minute
          .withTransformation(json)       // json is a static import from Transformer.json
          .withDecryption()               // enable decryption of the parameter value
          .get("/my/param", MyObj.class); // finally get the value
    ```

### Create your own Provider
You can create your own custom parameter store provider by implementing a handful of classes: 

=== "CustomProvider.java"

    ```java
    import java.util.Map;
    import software.amazon.lambda.powertools.parameters.BaseProvider;
    import software.amazon.lambda.powertools.parameters.cache.CacheManager;
    import software.amazon.lambda.powertools.parameters.transform.TransformationManager;
    
    /**
     * Our custom parameter provider itself. This does the heavy lifting of retrieving
     * parameters from whatever our underlying parameter store might be.
    **/
    public class CustomProvider extends BaseProvider {
    
        public CustomProvider(CacheManager cacheManager, TransformationManager transformationManager) {
            super(cacheManager, transformationManager);
        }

        public CustomProviderBuilder builder() {
            return new CustomProviderBuilder();
        }
    
        @Override
        protected String getValue(String key) {
            throw new RuntimeException("TODO - return a single value");
        }
    
        @Override
        protected Map<String, String> getMultipleValues(String path) {
            throw new RuntimeException("TODO - Optional - return multiple values");
        }
    }
    ```

=== "CustomProviderBuilder.java"

    ```java
    /**
     * Provides a builder-style interface to configure our @{link CustomProvider}.
    **/
    public class CustomProviderBuilder {
        private CacheManager cacheManager;
        private TransformationManager transformationManager;

        /**
         * Create a {@link CustomProvider} instance.
         *
         * @return a {@link CustomProvider}
         */
        public CustomProvider build() {
            if (cacheManager == null) {
                cacheManager = new CacheManager();
            }
            return new CustomProvider(cacheManager, transformationManager);
        }

        /**
         * Provide a CacheManager to the {@link CustomProvider}
         *
         * @param cacheManager the manager that will handle the cache of parameters
         * @return the builder to chain calls (eg. <pre>builder.withCacheManager().build()</pre>)
         */
        public CustomProviderBuilder withCacheManager(CacheManager cacheManager) {
            this.cacheManager = cacheManager;
            return this;
        }

        /**
         * Provide a transformationManager to the {@link CustomProvider}
         *
         * @param transformationManager the manager that will handle transformation of parameters
         * @return the builder to chain calls (eg. <pre>builder.withTransformationManager().build()</pre>)
         */
        public CustomProviderBuilder withTransformationManager(TransformationManager transformationManager) {
            this.transformationManager = transformationManager;
            return this;
        }
    }
    ```

=== "CustomProviderParam.java"
    
    ```java 
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    import software.amazon.lambda.powertools.parameters.transform.Transformer;
    
    /**
     * Aspect to inject a parameter from our custom provider. Note that if you
     * want to implement a provider _without_ an Aspect and field injection, you can
     * skip implementing both this and the {@link CustomProviderAspect} class.
    **/
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface CustomProviderParam {
        // The parameter key  
        String key();

        // The transformer to use
        Class<? extends Transformer> transformer() default Transformer.class;
    }
    ```

=== "CustomProviderAspect.java"

    ```java

    /**
     * Aspect to inject a parameter from our custom provider where the {@link CustomProviderParam}
     * annotation is used.
    **/
    @Aspect
    public class CustomProviderAspect extends BaseParamAspect {
    
        @Pointcut("get(* *) && @annotation(ddbConfigParam)")
        public void getParam(CustomProviderParam customConfigParam) {
        }
    
        @Around("getParam(customConfigParam)")
        public Object injectParam(final ProceedingJoinPoint joinPoint, final CustomProviderParam customConfigParam) { 
            BaseProvider provider = CustomProvider.builder().build();

            return getAndTransform(customConfigParam.key(), ddbConfigParam.transformer(), provider,
                    (FieldSignature) joinPoint.getSignature());
        }
    
    }
    ```
