

# Getting started with Amazon ElastiCache
<a name="GettingStarted"></a>

Use the hands-on tutorial in this section to help you get started and learn more about using ElastiCache.

**Topics**
+ [

# Setting up ElastiCache
](set-up.md)
+ [Create a Valkey serverless cache](GettingStarted.serverless-valkey.step1.md)
+ [Create a Redis OSS serverless cache](GettingStarted.serverless-redis.step1.md)
+ [Create a Memcached serverless cache](create-serverless-cache-mem.md)
+ [Network type for serverless caches](serverless-network-type.md)
+ [

# Tutorials: Getting started with Python and ElastiCache
](ElastiCache-Getting-Started-Tutorials.md)
+ [

# Tutorial: Configuring Lambda to access ElastiCache in a VPC
](LambdaRedis.md)

# Setting up ElastiCache
<a name="set-up"></a>

To use the ElastiCache web service, follow these steps.

**Topics**
+ [

## Sign up for an AWS account
](#sign-up-for-aws)
+ [

## Create a user with administrative access
](#create-an-admin)
+ [

## Grant programmatic access
](#elasticache-set-up-access-key)
+ [Set up permissions](#elasticache-set-up-permissions)
+ [

## Set up EC2
](#elasticache-install-configure-ec2)
+ [Grant network access](#elasticache-install-grant-access-VPN)
+ [Set up command line access](#Download-and-install-cli)

## Sign up for an AWS account
<a name="sign-up-for-aws"></a>

If you do not have an AWS account, complete the following steps to create one.

**To sign up for an AWS account**

1. Open [https://portal.aws.amazon.com/billing/signup](https://portal.aws.amazon.com/billing/signup).

1. Follow the online instructions.

   Part of the sign-up procedure involves receiving a phone call or text message and entering a verification code on the phone keypad.

   When you sign up for an AWS account, an *AWS account root user* is created. The root user has access to all AWS services and resources in the account. As a security best practice, assign administrative access to a user, and use only the root user to perform [tasks that require root user access](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user.html#root-user-tasks).

AWS sends you a confirmation email after the sign-up process is complete. At any time, you can view your current account activity and manage your account by going to [https://aws.amazon.com/](https://aws.amazon.com/) and choosing **My Account**.

## Create a user with administrative access
<a name="create-an-admin"></a>

After you sign up for an AWS account, secure your AWS account root user, enable AWS IAM Identity Center, and create an administrative user so that you don't use the root user for everyday tasks.

**Secure your AWS account root user**

1.  Sign in to the [AWS Management Console](https://console.aws.amazon.com/) as the account owner by choosing **Root user** and entering your AWS account email address. On the next page, enter your password.

   For help signing in by using root user, see [Signing in as the root user](https://docs.aws.amazon.com/signin/latest/userguide/console-sign-in-tutorials.html#introduction-to-root-user-sign-in-tutorial) in the *AWS Sign-In User Guide*.

1. Turn on multi-factor authentication (MFA) for your root user.

   For instructions, see [Enable a virtual MFA device for your AWS account root user (console)](https://docs.aws.amazon.com/IAM/latest/UserGuide/enable-virt-mfa-for-root.html) in the *IAM User Guide*.

**Create a user with administrative access**

1. Enable IAM Identity Center.

   For instructions, see [Enabling AWS IAM Identity Center](https://docs.aws.amazon.com//singlesignon/latest/userguide/get-set-up-for-idc.html) in the *AWS IAM Identity Center User Guide*.

1. In IAM Identity Center, grant administrative access to a user.

   For a tutorial about using the IAM Identity Center directory as your identity source, see [ Configure user access with the default IAM Identity Center directory](https://docs.aws.amazon.com//singlesignon/latest/userguide/quick-start-default-idc.html) in the *AWS IAM Identity Center User Guide*.

**Sign in as the user with administrative access**
+ To sign in with your IAM Identity Center user, use the sign-in URL that was sent to your email address when you created the IAM Identity Center user.

  For help signing in using an IAM Identity Center user, see [Signing in to the AWS access portal](https://docs.aws.amazon.com/signin/latest/userguide/iam-id-center-sign-in-tutorial.html) in the *AWS Sign-In User Guide*.

**Assign access to additional users**

1. In IAM Identity Center, create a permission set that follows the best practice of applying least-privilege permissions.

   For instructions, see [ Create a permission set](https://docs.aws.amazon.com//singlesignon/latest/userguide/get-started-create-a-permission-set.html) in the *AWS IAM Identity Center User Guide*.

1. Assign users to a group, and then assign single sign-on access to the group.

   For instructions, see [ Add groups](https://docs.aws.amazon.com//singlesignon/latest/userguide/addgroups.html) in the *AWS IAM Identity Center User Guide*.

## Grant programmatic access
<a name="elasticache-set-up-access-key"></a>

Users need programmatic access if they want to interact with AWS outside of the AWS Management Console. The way to grant programmatic access depends on the type of user that's accessing AWS.

To grant users programmatic access, choose one of the following options.


****  

| Which user needs programmatic access? | To | By | 
| --- | --- | --- | 
| IAM | (Recommended) Use console credentials as temporary credentials to sign programmatic requests to the AWS CLI, AWS SDKs, or AWS APIs. |  Following the instructions for the interface that you want to use. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonElastiCache/latest/dg/set-up.html)  | 
|  Workforce identity (Users managed in IAM Identity Center)  | Use temporary credentials to sign programmatic requests to the AWS CLI, AWS SDKs, or AWS APIs. |  Following the instructions for the interface that you want to use. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonElastiCache/latest/dg/set-up.html)  | 
| IAM | Use temporary credentials to sign programmatic requests to the AWS CLI, AWS SDKs, or AWS APIs. | Following the instructions in [Using temporary credentials with AWS resources](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html) in the IAM User Guide. | 
| IAM | (Not recommended)Use long-term credentials to sign programmatic requests to the AWS CLI, AWS SDKs, or AWS APIs. |  Following the instructions for the interface that you want to use. [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/AmazonElastiCache/latest/dg/set-up.html)  | 

**Related topics:**
+ [What is IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html) in the *IAM User Guide*.
+ [AWS Security Credentials](https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html) in *AWS General Reference*.

## Set up your permissions (new ElastiCache users only)
<a name="elasticache-set-up-permissions"></a>

To provide access, add permissions to your users, groups, or roles:
+ Users and groups in AWS IAM Identity Center:

  Create a permission set. Follow the instructions in [Create a permission set](https://docs.aws.amazon.com//singlesignon/latest/userguide/howtocreatepermissionset.html) in the *AWS IAM Identity Center User Guide*.
+ Users managed in IAM through an identity provider:

  Create a role for identity federation. Follow the instructions in [Create a role for a third-party identity provider (federation)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-idp.html) in the *IAM User Guide*.
+ IAM users:
  + Create a role that your user can assume. Follow the instructions in [Create a role for an IAM user](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_roles_create_for-user.html) in the *IAM User Guide*.
  + (Not recommended) Attach a policy directly to a user or add a user to a user group. Follow the instructions in [Adding permissions to a user (console)](https://docs.aws.amazon.com//IAM/latest/UserGuide/id_users_change-permissions.html#users_change_permissions-add-console) in the *IAM User Guide*.

Amazon ElastiCache creates and uses service-linked roles to provision resources and access other AWS resources and services on your behalf. For ElastiCache to create a service-linked role for you, use the AWS-managed policy named `AmazonElastiCacheFullAccess`. This role comes preprovisioned with permission that the service requires to create a service-linked role on your behalf.

You might decide not to use the default policy and instead to use a custom-managed policy. In this case, make sure that you have either permissions to call `iam:createServiceLinkedRole` or that you have created the ElastiCache service-linked role. 

For more information, see the following:
+ [Creating a New Policy](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_create.html) (IAM)
+ [AWS managed policies for Amazon ElastiCache](security-iam-awsmanpol.md)
+ [Using Service-Linked Roles for Amazon ElastiCache](using-service-linked-roles.md)

## Set up EC2
<a name="elasticache-install-configure-ec2"></a>

You will need to setup an EC2 instance from which you will connect to your cache.
+ If you don’t already have an EC2 instance, learn how to setup an EC2 instance here: [Amazon EC2 Getting Started Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EC2_GetStarted.html). 
+ Your EC2 instance must be in the same VPC and have the same security group settings as your cache. By default, Amazon ElastiCache creates a cache in your default VPC and uses the default security group. To follow this tutorial, ensure that your EC2 instance is in the default VPC and has the default security group.

## Grant network access from an Amazon VPC security group to your cache
<a name="elasticache-install-grant-access-VPN"></a>

ElastiCache node-based clusters use port 6379 for Valkey and Redis OSS commands, and ElastiCache serverless uses both port 6379 and port 6380. In order to successfully connect and execute Valkey or Redis OSS commands from your EC2 instance, your security group must allow access to these ports as needed.

For ElastiCache serverless specifically:
+ **Port 6379 (Primary endpoint):** Required for write operations and reads requiring strong consistency
+ **Port 6380 (Read-optimized endpoint):** Used for Read From Replica functionality, providing lower latency reads with eventual consistency

Many clients establish connections to both ports even if not actively using Read From Replica, requiring that you make port 6380 accessible even if you don't intend to use Read From Replica.

ElastiCache for Memcached uses the 11211 and 11212 ports to accept Memcached commands. In order to successfully connect and execute Memcached commands from your EC2 instance, your security group must allow access to these ports. 

1. Sign in to the AWS Command Line Interface and open the [Amazon EC2 console](https://console.aws.amazon.com/ec2/).

1. In the navigation pane, under **Network & Security**, choose **Security Groups**.

1. From the list of security groups, choose the security group for your Amazon VPC. Unless you created a security group for ElastiCache use, this security group will be named *default*.

1. Choose the Inbound tab, and then: 

   1. Choose **Edit**.

   1. Choose **Add rule**.

   1. In the Type column, choose **Custom TCP rule**.

   1. If using Valkey or Redis OSS, then in the **Port range** box, type `6379`.

      If using Memcached, then in the **Port range** box, type `11211`.

   1. In the **Source** box, choose **Anywhere** which has the port range (0.0.0.0/0) so that any Amazon EC2 instance that you launch within your Amazon VPC can connect to your cache. 

   1. If you are using ElastiCache serverless, add another rule by choosing **Add rule**.

   1. In the **Type** column, choose **Custom TCP** rule.

   1. If using ElastiCache for Redis OSS, then in the **Port range**box, type `6380`.

      If using ElastiCache for Memcached, then in the **Port range**box, type `11212`.

   1. In the **Source** box, choose **Anywhere** which has the port range (0.0.0.0/0) so that any Amazon EC2 instance that you launch within your Amazon VPC can connect to your cache.

   1. Choose **Save**

## Download and set up command line access
<a name="Download-and-install-cli"></a>

**Download and install the *valkey-cli* utility.**

If you use ElastiCache for Valkey, then you might find the valkey-cli utility useful. If you're using ElastiCache for Redis OSS with redis-cli, consider switching to valkey-cli as it works for Redis OSS as well.

1. Connect to your Amazon EC2 instance using the connection utility of your choice. For instructions on how to connect to an Amazon EC2 instance, see the [Amazon EC2 Getting Started Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EC2_GetStarted.html). 

1. Download and install valkey-cli utility by running the appropriate command for your setup.

   **Amazon Linux 2**

   ```
   sudo amazon-linux-extras install epel -y
   sudo yum install gcc jemalloc-devel openssl-devel tcl tcl-devel -y
   wget -O valkey-8.0.0.tar.gz https://github.com/valkey-io/valkey/archive/refs/tags/8.0.0.tar.gz
   tar xvzf valkey-8.0.0.tar.gz
   cd valkey-8.0.0
   make BUILD_TLS=yes
   ```

**Note**  
When you install the redis6 package, it installs redis6-cli with default encryption support.
It is important to have build support for TLS when installing valkey-cli or redis-cli. ElastiCache Serverless is only accessible when TLS is enabled.
If you are connecting to a cluster that isn't encrypted, you don't need the `Build_TLS=yes` option.

# Create a Valkey serverless cache
<a name="GettingStarted.serverless-valkey.step1"></a>

In this step, you create a new cache in Amazon ElastiCache.

**AWS Management Console**

To create a new cache using the ElastiCache console:

1. Sign in to the AWS Management Console and open the [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. In the navigation pane on the left side of the console, choose **Valkey caches**.

1. On the right side of the console, choose **Create Valkey cache**

1. In the **Cache settings** enter a **Name**. You can optionally enter a **description** for the cache. 

1. Leave the default settings selected.

1. Click **Create** to create the cache.

1. Once the cache is in "ACTIVE" status, you can begin writing and reading data to the cache. .

**AWS CLI**

The following AWS CLI example creates a new cache using create-serverless-cache. 

**Linux**

```
aws elasticache create-serverless-cache \
    --serverless-cache-name CacheName \
    --engine valkey
```

**Windows**

```
aws elasticache create-serverless-cache ^
    --serverless-cache-name CacheName ^
    --engine valkey
```

Note that the value of the Status field is set to `CREATING`.

To verify that ElastiCache has finished creating the cache, use the `describe-serverless-caches` command. 

**Linux**

```
aws elasticache describe-serverless-caches --serverless-cache-name CacheName
```

**Windows**

```
aws elasticache describe-serverless-caches --serverless-cache-name CacheName 
```

After creating the new cache, proceed to [Read and write data to the cache](GettingStarted.serverless-valkey.step2.md).

# Read and write data to the cache
<a name="GettingStarted.serverless-valkey.step2"></a>

This section assumes that you've created an Amazon EC2 instance and can connect to it. For instructions on how to do this, see the [Amazon EC2 Getting Started Guide](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EC2_GetStarted.html). 

This section also assumes that you have setup VPC access and security group settings for the EC2 instance from where you are connecting to your cache, and setup valkey-cli on your EC2 instance. For more information on that step see [Setting up ElastiCache](set-up.md). 

In addition to the steps below, if you have a large or global application you can greatly increase read performance by reading from replicas. For more information on this more advanced step see [Best Practices for using Read Replicas](ReadReplicas.md).

**Find your cache endpoint**

**AWS Management Console**

To find your cache’s endpoint using the ElastiCache console:

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/). 

1. In the navigation pane on the left side of the console, choose **Valkey caches**.

1. On the right side of the console, click on the name of the cache that you just created. 

1. In the **Cache details**, locate and copy the cache endpoint. 

**AWS CLI**

The following AWS CLI example shows to find the endpoint for your new cache using the describe-serverless-caches command. Once you have run the command, look for the "Endpoint" field.

**Linux**

```
aws elasticache describe-serverless-caches \
		--serverless-cache-name CacheName
```

**Windows**

```
aws elasticache describe-serverless-caches ^
		--serverless-cache-name CacheName
```

## Connect to your Valkey Cache (Linux)
<a name="w2aac14c15c37c29b1"></a>

Now that you have the endpoint you need, you can log in to your EC2 instance and connect to the cache. In the following example, you use the *valkey-cli* utility to connect to a cluster. The following command connects to a cache (note: replace cache-endpoint with the endpoint you retrieved in the previous step).

```
src/valkey-cli -h cache-endpoint --tls -p 6379
set a "hello"          // Set key "a" with a string value and no expiration
OK
get a                  // Get value for key "a"
"hello"
```

## Connect to your Valkey Cache (Windows)
<a name="w2aac14c15c37c29b3"></a>

Now that you have the endpoint you need, you can log in to your EC2 instance and connect to the cache. In the following example, you use the *valkey-cli* utility to connect to a cluster. The following command connects to a cache. Open the Command Prompt and change to the Valkey or Redis OSS directory and run the command (note: replace Cache\$1Endpoint with the endpoint you retrieved in the previous step).

```
c:\Valkey>valkey-cli -h Valkey_Cluster_Endpoint --tls -p 6379
set a "hello"          // Set key "a" with a string value and no expiration
OK
get a                  // Get value for key "a"
"hello"
```

You may now proceed to [(Optional) Clean up](GettingStarted.serverless-valkey.step3.md).

# (Optional) Clean up
<a name="GettingStarted.serverless-valkey.step3"></a>

If you no longer need the Amazon ElastiCache cache that you created, you can delete it. This step helps ensure that you are not charged for resources that you are not using. You can use the ElastiCache console, the AWS CLI, or the ElastiCache API to delete your cache.

**AWS Management Console**

To delete your cache using the console:

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/). 

1. In the navigation pane on the left side of the console, choose **Valkey Caches**.

1. Choose the radio button next to the cache you want to delete.

1. Select **Actions** on the top right, and select **Delete**.

1. You can optionally choose to take a final snapshot before you delete your cache. 

1. In the **Delete** confirmation screen, re-enter the cache name and choose **Delete** to delete the cluster, or choose **Cancel** to keep the cluster.

As soon as your cache moves in to the **DELETING** status, you stop incurring charges for it.

**AWS CLI**

The following AWS CLI example deletes a cache using the delete-serverless-cache command. 

**Linux**

```
aws elasticache delete-serverless-cache \
		--serverless-cache-name CacheName
```

**Windows**

```
aws elasticache delete-serverless-cache ^
		--serverless-cache-name CacheName
```

Note that the value of the **Status** field is set to **DELETING**. 

You may now proceed to [Next Steps](GettingStarted.serverless-valkey.next-steps.md).

# Next Steps
<a name="GettingStarted.serverless-valkey.next-steps"></a>

For more information about ElastiCache see the following pages:
+ [Working with ElastiCache](WorkingWithElastiCache.md)
+ [Scaling ElastiCache](Scaling.md)
+ [Logging and monitoring in Amazon ElastiCache](MonitoringECMetrics.md)
+ [ElastiCache best practices and caching strategies](BestPractices.md)
+ [Snapshot and restore](backups.md)
+ [Amazon SNS monitoring of ElastiCache events](ECEvents.md)

# Create a Redis OSS serverless cache
<a name="GettingStarted.serverless-redis.step1"></a>

In this step, you create a new cache in Amazon ElastiCache.

**AWS Management Console**

To create a new cache using the ElastiCache console:

1. Sign in to the AWS Management Console and open the ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. In the navigation pane on the left side of the console, choose **Redis OSS caches**.

1. On the right side of the console, choose **Create Redis OSS cache**

1. In the **Cache settings** enter a **Name**. You can optionally enter a **description** for the cache. 

1. Leave the default settings selected.

1. Click **Create** to create the cache.

1. Once the cache is in "ACTIVE" status, you can begin writing and reading data to the cache. .

**AWS CLI**

The following AWS CLI example creates a new cache using create-serverless-cache. 

**Linux**

```
aws elasticache create-serverless-cache \
    --serverless-cache-name CacheName \
    --engine redis
```

**Windows**

```
aws elasticache create-serverless-cache ^
    --serverless-cache-name CacheName ^
    --engine redis
```

Note that the value of the Status field is set to `CREATING`.

To verify that ElastiCache has finished creating the cache, use the `describe-serverless-caches` command. 

**Linux**

```
aws elasticache describe-serverless-caches --serverless-cache-name CacheName
```

**Windows**

```
aws elasticache describe-serverless-caches --serverless-cache-name CacheName 
```

After creating the new cache, proceed to [Read and write data to the cache](GettingStarted.serverless-redis.step2.md).

# Read and write data to the cache
<a name="GettingStarted.serverless-redis.step2"></a>

This section assumes that you've created an Amazon EC2 instance and can connect to it. For instructions on how to do this, see the [Amazon EC2 Getting Started Guide](https://aws.amazon.com/ec2/getting-started/). 

This section also assumes that you have setup VPC access and security group settings for the EC2 instance from where you are connecting to your cache, and setup valkey-cli on your EC2 instance. For more information on that step see [Setting up ElastiCache](set-up.md). 

**Find your cache endpoint**

**AWS Management Console**

To find your cache’s endpoint using the ElastiCache console:

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/). 

1. In the navigation pane on the left side of the console, choose **Valkey caches** **Redis OSS caches**.

1. On the right side of the console, click on the name of the cache that you just created. 

1. In the **Cache details**, locate and copy the cache endpoint. 

**AWS CLI**

The following AWS CLI example shows to find the endpoint for your new cache using the describe-serverless-caches command. Once you have run the command, look for the "Endpoint" field.

**Linux**

```
aws elasticache describe-serverless-caches \
		--serverless-cache-name CacheName
```

**Windows**

```
aws elasticache describe-serverless-caches ^
		--serverless-cache-name CacheName
```

## Connect to your Valkey or Redis OSS Cache (Linux)
<a name="w2aac14c19c37c27b1"></a>

Now that you have the endpoint you need, you can log in to your EC2 instance and connect to the cache. In the following example, you use the *valkey-cli* utility to connect to a cluster. The following command connects to a cache (note: replace cache-endpoint with the endpoint you retrieved in the previous step).

```
src/valkey-cli -h cache-endpoint --tls -p 6379
set a "hello"          // Set key "a" with a string value and no expiration
OK
get a                  // Get value for key "a"
"hello"
```

## Connect to your Valkey or Redis OSS Cache (Windows)
<a name="w2aac14c19c37c27b3"></a>

Now that you have the endpoint you need, you can log in to your EC2 instance and connect to the cache. In the following example, you use the *valkey-cli* utility to connect to a cluster. The following command connects to a cache. Open the Command Prompt and change to the Valkey directory and run the command (note: replace Cache\$1Endpoint with the endpoint you retrieved in the previous step).

```
c:\Redis>valkey-cli -h Redis_Cluster_Endpoint --tls -p 6379
set a "hello"          // Set key "a" with a string value and no expiration
OK
get a                  // Get value for key "a"
"hello"
```

You may now proceed to [(Optional) Clean up](GettingStarted.serverless-redis.step3.md).

# (Optional) Clean up
<a name="GettingStarted.serverless-redis.step3"></a>

If you no longer need the Amazon ElastiCache cache that you created, you can delete it. This step helps ensure that you are not charged for resources that you are not using. You can use the ElastiCache console, the AWS CLI, or the ElastiCache API to delete your cache.

**AWS Management Console**

To delete your cache using the console:

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/). 

1. In the navigation pane on the left side of the console, choose **Valkey or Redis OSS Caches**.

1. Choose the radio button next to the cache you want to delete.

1. Select **Actions** on the top right, and select **Delete**.

1. You can optionally choose to take a final snapshot before you delete your cache. 

1. In the **Delete** confirmation screen, re-enter the cache name and choose **Delete** to delete the cluster, or choose **Cancel** to keep the cluster.

As soon as your cache moves in to the **DELETING** status, you stop incurring charges for it.

**AWS CLI**

The following AWS CLI example deletes a cache using the delete-serverless-cache command. 

**Linux**

```
aws elasticache delete-serverless-cache \
		--serverless-cache-name CacheName
```

**Windows**

```
aws elasticache delete-serverless-cache ^
		--serverless-cache-name CacheName
```

Note that the value of the **Status** field is set to **DELETING**. 

You may now proceed to [Next Steps](GettingStarted.serverless-redis.next-steps.md).

# Next Steps
<a name="GettingStarted.serverless-redis.next-steps"></a>

For more information about ElastiCache see the following pages:
+ [Working with ElastiCache](WorkingWithElastiCache.md)
+ [Scaling ElastiCache](Scaling.md)
+ [Logging and monitoring in Amazon ElastiCache](MonitoringECMetrics.md)
+ [ElastiCache best practices and caching strategies](BestPractices.md)
+ [Snapshot and restore](backups.md)
+ [Amazon SNS monitoring of ElastiCache events](ECEvents.md)

# Create a Memcached serverless cache
<a name="create-serverless-cache-mem"></a>

**AWS Management Console**

To create a new Memcached serverless cache using the ElastiCache console:

1. Sign in to the AWS Management Console and open the ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. In the navigation pane on the left side of the console, choose **Memcached Caches**.

1. On the right side of the console, choose **Create Memcached cache**.

1. In the **Cache settings** enter a **Name**. You can optionally enter a **description** for the cache. 

1. Leave the default settings selected. 

1. Click **Create** to create the cache. 

1. Once the cache is in "ACTIVE" status, you can begin writing and reading data to the cache. 

To create a new cache using the AWS CLI

The following AWS CLI example creates a new cache using create-serverless-cache.

**Linux**

```
aws elasticache create-serverless-cache \
		--serverless-cache-name CacheName \
		--engine memcached
```

**Windows**

```
aws elasticache create-serverless-cache ^
		--serverless-cache-name CacheName ^
		--engine memcached
```

Note that the value of the Status field is set to `CREATING`.

To verify that ElastiCache has finished creating the cache, use the `describe-serverless-caches` command.

**Linux**

```
aws elasticache describe-serverless-caches --serverless-cache-name CacheName
```

**Windows**

```
aws elasticache describe-serverless-caches --serverless-cache-name CacheName
```

After creating the new cache, proceed to [Read and write data to the cache](read-write-cache-mem.md).

# Read and write data to the cache
<a name="read-write-cache-mem"></a>

This section assumes that you've created an Amazon EC2 instance and can connect to it. For instructions on how to do this, see the [Amazon EC2 Getting Started Guide](https://aws.amazon.com/ec2/getting-started/). 

By default, ElastiCache creates a cache in your default VPC. Make sure that your EC2 instance is also created in the default VPC, so that it is able to connect to the cache. 

**Find your cache endpoint**

**AWS Management Console**

To find your cache’s endpoint using the ElastiCache console:

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/). 

1. In the navigation pane on the left side of the console, choose **Memcached Caches**.

1. On the right side of the console, click on the name of the cache that you just created. 

1. In the **Cache details**, locate and copy the cache endpoint. 

**AWS CLI**

The following AWS CLI example shows to find the endpoint for your new cache using the describe-serverless-caches command. Once you have run the command, look for the "Endpoint" field. 

**Linux**

```
aws elasticache describe-serverless-caches \
		--serverless-cache-name CacheName
```

**Windows**

```
aws elasticache describe-serverless-caches ^
		--serverless-cache-name CacheName
```

## Connect using OpenSSL
<a name="w2aac14c21c41c29b1"></a>

 For information on how to connect using OpenSSL, see [ElastiCache in-transit encryption (TLS)](in-transit-encryption.md)

## Connect using Memcached Java client
<a name="w2aac14c21c41c29b3"></a>

```
import java.security.KeyStore;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import net.spy.memcached.AddrUtil;
import net.spy.memcached.ConnectionFactoryBuilder;
import net.spy.memcached.FailureMode;
import net.spy.memcached.MemcachedClient;

public class TLSDemo {
    public static void main(String[] args) throws Exception {
        ConnectionFactoryBuilder connectionFactoryBuilder = new ConnectionFactoryBuilder();
        // Build SSLContext
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init((KeyStore) null);
        SSLContext sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, tmf.getTrustManagers(), null);
        // Create the client in TLS mode
        connectionFactoryBuilder.setSSLContext(sslContext);
        // Set Failure Mode to Retry
        connectionFactoryBuilder.setFailureMode(FailureMode.Retry);
        MemcachedClient client = new MemcachedClient(connectionFactoryBuilder.build(), AddrUtil.getAddresses("mycluster-fnjyzo.serverless.use1.cache.amazonaws.com:11211"));

        // Store a data item for an hour.
        client.set("theKey", 3600, "This is the data value");
    }
}
```

## Connect using Memcached PHP client
<a name="w2aac14c21c41c29b5"></a>

```
<?php
$cluster_endpoint = "mycluster.serverless.use1.cache.amazonaws.com";
$server_port = 11211; 

/* Initialize a persistent Memcached client in TLS mode */
$tls_client = new Memcached('persistent-id');
$tls_client->addServer($cluster_endpoint, $server_port);
if(!$tls_client->setOption(Memcached::OPT_USE_TLS, 1)) {
    echo $tls_client->getLastErrorMessage(), "\n";
    exit(1);
}
$tls_config = new MemcachedTLSContextConfig();
$tls_config->hostname = '*.serverless.use1.cache.amazonaws.com';
$tls_config->skip_cert_verify = false;
$tls_config->skip_hostname_verify = false;
$tls_client->createAndSetTLSContext((array)$tls_config); 

 /* store the data for 60 seconds in the cluster */
$tls_client->set('key', 'value', 60);
?>
```

## Connect using Memcached Python client (Pymemcache)
<a name="w2aac14c21c41c29b7"></a>

See [https://pymemcache.readthedocs.io/en/latest/getting\$1started.html](https://pymemcache.readthedocs.io/en/latest/getting_started.html)

```
import ssl
from pymemcache.client.base import Client
		
context = ssl.create_default_context()
cluster_endpoint = <To be taken from the AWS CLI / console>
target_port = 11211
memcached_client = Client(("{cluster_endpoint}", target_port), tls_context=context)
memcached_client.set("key", "value", expire=500, noreply=False)
assert self.memcached_client.get("key").decode() == "value"
```

## Connect using Memcached NodeJS/TS client (Electrode-IO memcache)
<a name="w2aac14c21c41c29b9"></a>

See [https://github.com/electrode-io/memcache](https://github.com/electrode-io/memcache) and [https://www.npmjs.com/package/memcache-client](https://www.npmjs.com/package/memcache-client)

Install via `npm i memcache-client`

In the application, create a memcached TLS client as follows:

```
var memcache = require("memcache-client");
const client = new memcache.MemcacheClient({server: "{cluster_endpoint}:11211", tls: {}});
client.set("key", "value");
```

## Connect using Memcached Rust client (rust-memcache)
<a name="w2aac14c21c41c29c11"></a>

See [https://crates.io/crates/memcache](https://crates.io/crates/memcache) and [https://github.com/aisk/rust-memcache](https://github.com/aisk/rust-memcache).

```
// create connection with to memcached server node:
let client = memcache::connect("memcache+tls://<cluster_endpoint>:11211?verify_mode=none").unwrap();
				
// set a string value
client.set("foo", "bar", 0).unwrap();
```

## Connect using Memcached Go client (Gomemcache)
<a name="w2aac14c21c41c29c13"></a>

See [https://github.com/bradfitz/gomemcache](https://github.com/bradfitz/gomemcache)

```
c := New(net.JoinHostPort("{cluster_endpoint}", strconv.Itoa(port)))
c.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) {
var td tls.Dialer
td.Config = &tls.Config{}
return td.DialContext(ctx, network, addr)
}
foo := &Item{Key: "foo", Value: []byte("fooval"), Flags: 123}
err := c.Set(foo)
```

## Connect using Memcached Ruby client (Dalli)
<a name="w2aac14c21c41c29c15"></a>

See [https://github.com/petergoldstein/dalli](https://github.com/petergoldstein/dalli)

```
require 'dalli'
ssl_context = OpenSSL::SSL::SSLContext.new
ssl_context.ssl_version = :SSLv23
ssl_context.verify_hostname = true
ssl_context.verify_mode = OpenSSL::SSL::VERIFY_PEER
client = Dalli::Client.new("<cluster_endpoint>:11211", :ssl_context => ssl_context); 
client.get("abc")
```

## Connect using Memcached .NET client (EnyimMemcachedCore)
<a name="w2aac14c21c41c29c17"></a>

See [https://github.com/cnblogs/EnyimMemcachedCore](https://github.com/cnblogs/EnyimMemcachedCore)

```
"MemcachedClient": {
"Servers": [
{
"Address": "{cluster_endpoint}",
"Port": 11211
}
],
"UseSslStream":  true
}
```

You may now proceed to [(Optional) Clean up](read-write-cleanup-mem.md).

# (Optional) Clean up
<a name="read-write-cleanup-mem"></a>

**Using the AWS Management Console**

The following procedure deletes a single cache from your deployment. To delete multiple caches, repeat the procedure for each cache that you want to delete. You do not need to wait for one cache to finish deleting before starting the procedure to delete another cache.

**To delete a cache**

1. Sign in to the AWS Management Console and open the Amazon ElastiCache console at [https://console.aws.amazon.com/elasticache/](https://console.aws.amazon.com/elasticache/).

1. In the ElastiCache console dashboard, choose the engine that is running on the cache that you want to delete. A list of all caches running that engine appears.

1. To choose the cache to delete, choose the cache's name from the list of caches.
**Important**  
 You can only delete one cache at a time from the ElastiCache console. Choosing multiple caches disables the delete operation.

1. For **Actions**, choose **Delete**.

1. In the **Delete Cache** confirmation screen, choose **Delete** to delete the cache, or choose **Cancel** to keep the cluster.

1. If you chose **Delete**, the status of the cache changes to *deleting*.

As soon as your cache moves in to the **DELETING** status, you stop incurring charges for it.

**Using the AWS CLI**

The following code deletes the cache my-cache.

```
aws elasticache delete-serverless-cache --serverless-cache-name my-cache
```

The delete-serverless-cache CLI action only deletes one serverless cache. To delete multiple caches, call delete-serverless-cache for each serverless cache that you want to delete. You do not need to wait for one serverless cache to finish deleting before deleting another.

**For Linux, macOS, or Unix:**

```
aws elasticache delete-serverless-cache \
		--serverless-cache-name my-cache
```

**For Windows:**

```
aws elasticache delete-serverless-cache ^
		--serverless-cache-name my-cache
```

For more information, see the AWS CLI for ElastiCache topic delete-serverless-cache.

You may now proceed to [Next Steps](next-steps-mem.md).

# Next Steps
<a name="next-steps-mem"></a>

For more information about ElastiCache see:
+ [Working with ElastiCache](WorkingWithElastiCache.md)
+ [Scaling ElastiCache](Scaling.md)
+ [Quotas for ElastiCache](quota-limits.md)
+ [ElastiCache best practices and caching strategies](BestPractices.md)
+ [Viewing ElastiCache events](ECEvents.Viewing.md)

# Choosing a network type for serverless caches
<a name="serverless-network-type"></a>

ElastiCache serverless caches support the Internet Protocol versions 4 and 6 (IPv4 and IPv6). When creating a serverless cache, you choose one of the following network types:
+ **IPv4** – The cache accepts only IPv4 connections.
+ **IPv6** – The cache accepts only IPv6 connections.
+ **Dual stack** – The cache accepts both IPv4 and IPv6 connections.

For dual stack serverless caches, the IP protocol used for a connection depends on how your client resolves the cache endpoint's DNS hostname.

There are no additional charges for accessing ElastiCache over IPv6.

**Note**  
The network type can only be set when creating a serverless cache. You cannot change the network type after the cache is created.

## Configuring subnets for network type
<a name="serverless-network-type-subnets"></a>

When you create a serverless cache, you can provide subnet IDs. ElastiCache uses those subnets to allocate IP addresses for your cache. The subnets you provide must support the network type you choose:
+ **IPv4** – Subnets must have IPv4 address space. Dual stack subnets (with both IPv4 and IPv6) are also supported.
+ **IPv6** – Subnets must be IPv6-only. Dual stack subnets are not supported.
+ **Dual stack** – Subnets must have both IPv4 and IPv6 address space.

If you do not specify a network type, ElastiCache defaults to IPv4 unless all provided subnets are IPv6-only, in which case it defaults to IPv6. If you do not provide subnet IDs, ElastiCache selects default subnets in your VPC.

## Using the AWS Management Console
<a name="serverless-network-type-console"></a>

When creating a serverless cache using the console, choose **Customize default settings** under **Default settings**. In the **Connectivity** section, choose a **Network type**: **IPv4**, **IPv6**, or **Dual stack**. IPv4 is selected by default.

## Using the AWS CLI
<a name="serverless-network-type-cli"></a>

When creating a serverless cache using the AWS CLI, use the `--network-type` parameter with the **create-serverless-cache** command.

For Linux, macOS, or Unix:

```
aws elasticache create-serverless-cache \
  --serverless-cache-name <cache-name> \
  --engine <engine> \
  --network-type <network-type> \
  --subnet-ids <subnet-id-1> <subnet-id-2>
```

For Windows:

```
aws elasticache create-serverless-cache ^
  --serverless-cache-name <cache-name> ^
  --engine <engine> ^
  --network-type <network-type> ^
  --subnet-ids <subnet-id-1> <subnet-id-2>
```

Replace:
+ *<cache-name>* – A name for your serverless cache.
+ *<engine>* – The engine for your cache: `valkey`, `redis`, or `memcached`.
+ *<network-type>* – The network type: `ipv4`, `ipv6`, or `dual_stack`.
+ *<subnet-id-1>*, *<subnet-id-2>* – The IDs of the subnets for your cache. The subnets must support the chosen network type.

For more information about the **create-serverless-cache** command, see [create-serverless-cache](https://docs.aws.amazon.com/cli/latest/reference/elasticache/create-serverless-cache.html) in the AWS CLI reference.

For information about choosing a network type for node-based clusters, see [Choosing a network type in ElastiCache](network-type.md).

# Tutorials: Getting started with Python and ElastiCache
<a name="ElastiCache-Getting-Started-Tutorials"></a>

This section contains hands-on tutorials to help you learn about ElastiCache for Valkey and Redis OSS. We encourage you to work through one of the language-specific tutorials. 

**Note**  
AWS SDKs are available for a wide variety of languages. For a complete list, see [Tools for Amazon Web Services](https://aws.amazon.com/tools/).

**Topics**
+ [

# Python and ElastiCache
](ElastiCache-Getting-Started-Tutorials-Python.md)

# Python and ElastiCache
<a name="ElastiCache-Getting-Started-Tutorials-Python"></a>

In this tutorial, you use the AWS SDK for Python (Boto3) to write simple programs to perform the following ElastiCache operations:
+ Create ElastiCache for Redis OSS clusters (cluster mode enabled and cluster mode disabled)
+ Check if users or user groups exist, otherwise create them. (This feature is availably with Valkey 7.2 and onwards, and with Redis OSS 6.0 to 7.1.)
+ Connect to ElastiCache
+ Perform operations such as setting and getting strings, reading from and writing to steams and publishing and subscribing from Pub/Sub channel.

As you work through this tutorial, you can refer to the AWS SDK for Python (Boto) documentation. The following section is specific to ElastiCache: [ElastiCache low-level client](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/elasticache.html)

## Tutorial Prerequisites
<a name="ElastiCache-Getting-Started-Tutorials-Prerquisites"></a>
+ Set up an AWS access key to use the AWS SDKs. For more information, see [Setting up ElastiCache](set-up.md).
+ Install Python 3.0 or later. For more information, see [https://www.python.org/downloads](https://www.python.org/downloads). For instructions, see [Quickstart](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html) in the Boto 3 documentation.

**Topics**
+ [

## Tutorial Prerequisites
](#ElastiCache-Getting-Started-Tutorials-Prerquisites)
+ [

## Tutorial: Creating ElastiCache clusters and users
](#ElastiCache-Getting-Started-Tutorials-Create-Cluster-and-Users)
+ [

## Tutorial: Connecting to ElastiCache
](#ElastiCache-Getting-Started-Tutorials-Connecting)
+ [

## Usage examples
](#ElastiCache-Getting-Started-Tutorials-Usage)

## Tutorial: Creating ElastiCache clusters and users
<a name="ElastiCache-Getting-Started-Tutorials-Create-Cluster-and-Users"></a>

The following examples use the boto3 SDK for ElastiCache for Redis OSS management operations (cluster or user creation) and redis-py/redis-py-cluster for data handling.

**Topics**
+ [

### Create a cluster mode disabled cluster
](#ElastiCache-Getting-Started-Tutorials-Create-Cluster)
+ [

### Create a cluster mode disabled cluster with TLS and RBAC
](#ElastiCache-Getting-Started-Tutorials-RBAC)
+ [

### Create a cluster mode enabled cluster
](#ElastiCache-Getting-Started-Tutorials-Cluster-Enabled)
+ [

### Create a cluster mode enabled cluster with TLS and RBAC
](#ElastiCache-Getting-Started-Tutorials-Cluster-RBAC)
+ [

### Check if users/usergroup exists, otherwise create them
](#ElastiCache-Getting-Started-Tutorials-Users)

### Create a cluster mode disabled cluster
<a name="ElastiCache-Getting-Started-Tutorials-Create-Cluster"></a>

Copy the following program and paste it into a file named *CreateClusterModeDisabledCluster.py*.

```
import boto3
import logging

logging.basicConfig(level=logging.INFO)
client = boto3.client('elasticache')

def create_cluster_mode_disabled(CacheNodeType='cache.t3.small',EngineVersion='6.0',NumCacheClusters=2,ReplicationGroupDescription='Sample cluster',ReplicationGroupId=None):
    """Creates an ElastiCache Cluster with cluster mode disabled

    Returns a dictionary with the API response

    :param CacheNodeType: Node type used on the cluster. If not specified, cache.t3.small will be used
    Refer to https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/CacheNodes.SupportedTypes.html for supported node types
    :param EngineVersion: Engine version to be used. If not specified, latest will be used.
    :param NumCacheClusters: Number of nodes in the cluster. Minimum 1 (just a primary node) and maximun 6 (1 primary and 5 replicas).
    If not specified, cluster will be created with 1 primary and 1 replica.
    :param ReplicationGroupDescription: Description for the cluster.
    :param ReplicationGroupId: Name for the cluster
    :return: dictionary with the API results

    """
    if not ReplicationGroupId:
        return 'ReplicationGroupId parameter is required'

    response = client.create_replication_group(
        AutomaticFailoverEnabled=True,
        CacheNodeType=CacheNodeType,
        Engine='valkey',
        EngineVersion=EngineVersion,
        NumCacheClusters=NumCacheClusters,
        ReplicationGroupDescription=ReplicationGroupDescription,
        ReplicationGroupId=ReplicationGroupId,
        SnapshotRetentionLimit=30,
    )
    return response


if __name__ == '__main__':
    
    # Creates an ElastiCache Cluster mode disabled cluster, based on cache.m6g.large nodes, Valkey 8.0, one primary and two replicas
    elasticacheResponse = create_cluster_mode_disabled(
        #CacheNodeType='cache.m6g.large', 
        EngineVersion='8.0',
        NumCacheClusters=3,
        ReplicationGroupDescription='Valkey cluster mode disabled with replicas',
        ReplicationGroupId='valkey202104053'
        )
    
    logging.info(elasticacheResponse)
```

To run the program, enter the following command:

 `python CreateClusterModeDisabledCluster.py`

For more information, see [Managing clusters in ElastiCache](Clusters.md).

### Create a cluster mode disabled cluster with TLS and RBAC
<a name="ElastiCache-Getting-Started-Tutorials-RBAC"></a>

To ensure security, you can use Transport Layer Security (TLS) and Role-Based Access Control (RBAC) when creating a cluster mode disabled cluster. Unlike Valkey or Redis OSS AUTH, where all authenticated clients have full replication group access if their token is authenticated, RBAC enables you to control cluster access through user groups. These user groups are designed as a way to organize access to replication groups. For more information, see [Role-Based Access Control (RBAC)](Clusters.RBAC.md).

Copy the following program and paste it into a file named *ClusterModeDisabledWithRBAC.py*.

```
import boto3
import logging

logging.basicConfig(level=logging.INFO)
client = boto3.client('elasticache')

def create_cluster_mode_disabled_rbac(CacheNodeType='cache.t3.small',EngineVersion='6.0',NumCacheClusters=2,ReplicationGroupDescription='Sample cluster',ReplicationGroupId=None, UserGroupIds=None, SecurityGroupIds=None,CacheSubnetGroupName=None):
    """Creates an ElastiCache Cluster with cluster mode disabled and RBAC

    Returns a dictionary with the API response

    :param CacheNodeType: Node type used on the cluster. If not specified, cache.t3.small will be used
    Refer to https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/CacheNodes.SupportedTypes.html for supported node types
    :param EngineVersion: Engine version to be used. If not specified, latest will be used.
    :param NumCacheClusters: Number of nodes in the cluster. Minimum 1 (just a primary node) and maximun 6 (1 primary and 5 replicas).
    If not specified, cluster will be created with 1 primary and 1 replica.
    :param ReplicationGroupDescription: Description for the cluster.
    :param ReplicationGroupId: Mandatory name for the cluster.
    :param UserGroupIds: The ID of the user group to be assigned to the cluster.
    :param SecurityGroupIds: List of security groups to be assigned. If not defined, default will be used
    :param CacheSubnetGroupName: subnet group where the cluster will be placed. If not defined, default will be used.
    :return: dictionary with the API results

    """
    if not ReplicationGroupId:
        return {'Error': 'ReplicationGroupId parameter is required'}
    elif not isinstance(UserGroupIds,(list)):
        return {'Error': 'UserGroupIds parameter is required and must be a list'}

    params={'AutomaticFailoverEnabled': True, 
            'CacheNodeType': CacheNodeType, 
            'Engine': 'valkey', 
            'EngineVersion': EngineVersion, 
            'NumCacheClusters': NumCacheClusters, 
            'ReplicationGroupDescription': ReplicationGroupDescription, 
            'ReplicationGroupId': ReplicationGroupId, 
            'SnapshotRetentionLimit': 30, 
            'TransitEncryptionEnabled': True, 
            'UserGroupIds':UserGroupIds
        }

    # defaults will be used if CacheSubnetGroupName or SecurityGroups are not explicit.
    if isinstance(SecurityGroupIds,(list)):
        params.update({'SecurityGroupIds':SecurityGroupIds})
    if CacheSubnetGroupName:
        params.update({'CacheSubnetGroupName':CacheSubnetGroupName})

    response = client.create_replication_group(**params)
    return response

if __name__ == '__main__':

    # Creates an ElastiCache Cluster mode disabled cluster, based on cache.m6g.large nodes, Valkey 8.0, one primary and two replicas.
    # Assigns the existent user group "mygroup" for RBAC authentication
   
    response=create_cluster_mode_disabled_rbac(
        CacheNodeType='cache.m6g.large',
        EngineVersion='8.0',
        NumCacheClusters=3,
        ReplicationGroupDescription='Valkey cluster mode disabled with replicas',
        ReplicationGroupId='valkey202104',
        UserGroupIds=[
            'mygroup'
        ],
        SecurityGroupIds=[
            'sg-7cc73803'
        ],
        CacheSubnetGroupName='default'
    )

    logging.info(response)
```

To run the program, enter the following command:

 `python ClusterModeDisabledWithRBAC.py`

For more information, see [Managing clusters in ElastiCache](Clusters.md).

### Create a cluster mode enabled cluster
<a name="ElastiCache-Getting-Started-Tutorials-Cluster-Enabled"></a>

Copy the following program and paste it into a file named *ClusterModeEnabled.py*.

```
import boto3
import logging

logging.basicConfig(level=logging.INFO)
client = boto3.client('elasticache')

def create_cluster_mode_enabled(CacheNodeType='cache.t3.small',EngineVersion='6.0',NumNodeGroups=1,ReplicasPerNodeGroup=1, ReplicationGroupDescription='Sample cache with cluster mode enabled',ReplicationGroupId=None):
    """Creates an ElastiCache Cluster with cluster mode enabled

    Returns a dictionary with the API response

    :param CacheNodeType: Node type used on the cluster. If not specified, cache.t3.small will be used
    Refer to https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/CacheNodes.SupportedTypes.html for supported node types
    :param EngineVersion: Engine version to be used. If not specified, latest will be used.
    :param NumNodeGroups: Number of shards in the cluster. Minimum 1 and maximun 90.
    If not specified, cluster will be created with 1 shard.
    :param ReplicasPerNodeGroup: Number of replicas per shard. If not specified 1 replica per shard will be created.
    :param ReplicationGroupDescription: Description for the cluster.
    :param ReplicationGroupId: Name for the cluster
    :return: dictionary with the API results

    """
    if not ReplicationGroupId:
        return 'ReplicationGroupId parameter is required'
    
    response = client.create_replication_group(
        AutomaticFailoverEnabled=True,
        CacheNodeType=CacheNodeType,
        Engine='valkey',
        EngineVersion=EngineVersion,
        ReplicationGroupDescription=ReplicationGroupDescription,
        ReplicationGroupId=ReplicationGroupId,
    #   Creates a cluster mode enabled cluster with 1 shard(NumNodeGroups), 1 primary node (implicit) and 2 replicas (replicasPerNodeGroup)
        NumNodeGroups=NumNodeGroups,
        ReplicasPerNodeGroup=ReplicasPerNodeGroup,
        CacheParameterGroupName='default.valkey7.2.cluster.on'
    )

    return response


# Creates a cluster mode enabled 
response = create_cluster_mode_enabled(
    CacheNodeType='cache.m6g.large',
    EngineVersion='6.0',
    ReplicationGroupDescription='Valkey cluster mode enabled with replicas',
    ReplicationGroupId='valkey20210',
#   Creates a cluster mode enabled cluster with 1 shard(NumNodeGroups), 1 primary (implicit) and 2 replicas (replicasPerNodeGroup)
    NumNodeGroups=2,
    ReplicasPerNodeGroup=1,
)

logging.info(response)
```

To run the program, enter the following command:

 `python ClusterModeEnabled.py`

For more information, see [Managing clusters in ElastiCache](Clusters.md).

### Create a cluster mode enabled cluster with TLS and RBAC
<a name="ElastiCache-Getting-Started-Tutorials-Cluster-RBAC"></a>

To ensure security, you can use Transport Layer Security (TLS) and Role-Based Access Control (RBAC) when creating a cluster mode enabled cluster. Unlike Valkey or Redis OSS AUTH, where all authenticated clients have full replication group access if their token is authenticated, RBAC enables you to control cluster access through user groups. These user groups are designed as a way to organize access to replication groups. For more information, see [Role-Based Access Control (RBAC)](Clusters.RBAC.md).

Copy the following program and paste it into a file named *ClusterModeEnabledWithRBAC.py*.

```
import boto3
import logging

logging.basicConfig(level=logging.INFO)
client = boto3.client('elasticache')

def create_cluster_mode_enabled(CacheNodeType='cache.t3.small',EngineVersion='6.0',NumNodeGroups=1,ReplicasPerNodeGroup=1, ReplicationGroupDescription='Sample cache with cluster mode enabled',ReplicationGroupId=None,UserGroupIds=None, SecurityGroupIds=None,CacheSubnetGroupName=None,CacheParameterGroupName='default.valkey7.2.cluster.on'):
    """Creates an ElastiCache Cluster with cluster mode enabled and RBAC

    Returns a dictionary with the API response

    :param CacheNodeType: Node type used on the cluster. If not specified, cache.t3.small will be used
    Refer to https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/CacheNodes.SupportedTypes.html for supported node types
    :param EngineVersion: Engine version to be used. If not specified, latest will be used.
    :param NumNodeGroups: Number of shards in the cluster. Minimum 1 and maximun 90.
    If not specified, cluster will be created with 1 shard.
    :param ReplicasPerNodeGroup: Number of replicas per shard. If not specified 1 replica per shard will be created.
    :param ReplicationGroupDescription: Description for the cluster.
    :param ReplicationGroupId: Name for the cluster.
    :param CacheParameterGroupName: Parameter group to be used. Must be compatible with the engine version and cluster mode enabled.
    :return: dictionary with the API results

    """
    if not ReplicationGroupId:
        return 'ReplicationGroupId parameter is required'
    elif not isinstance(UserGroupIds,(list)):
        return {'Error': 'UserGroupIds parameter is required and must be a list'}

    params={'AutomaticFailoverEnabled': True, 
            'CacheNodeType': CacheNodeType, 
            'Engine': 'valkey', 
            'EngineVersion': EngineVersion, 
            'ReplicationGroupDescription': ReplicationGroupDescription, 
            'ReplicationGroupId': ReplicationGroupId, 
            'SnapshotRetentionLimit': 30, 
            'TransitEncryptionEnabled': True, 
            'UserGroupIds':UserGroupIds,
            'NumNodeGroups': NumNodeGroups,
            'ReplicasPerNodeGroup': ReplicasPerNodeGroup,
            'CacheParameterGroupName': CacheParameterGroupName
        }

    # defaults will be used if CacheSubnetGroupName or SecurityGroups are not explicit.
    if isinstance(SecurityGroupIds,(list)):
        params.update({'SecurityGroupIds':SecurityGroupIds})
    if CacheSubnetGroupName:
        params.update({'CacheSubnetGroupName':CacheSubnetGroupName})

    response = client.create_replication_group(**params)
    return response

if __name__ == '__main__':
    # Creates a cluster mode enabled cluster
    response = create_cluster_mode_enabled(
        CacheNodeType='cache.m6g.large',
        EngineVersion='7.2',
        ReplicationGroupDescription='Valkey cluster mode enabled with replicas',
        ReplicationGroupId='valkey2021',
    #   Creates a cluster mode enabled cluster with 1 shard(NumNodeGroups), 1 primary (implicit) and 2 replicas (replicasPerNodeGroup)
        NumNodeGroups=2,
        ReplicasPerNodeGroup=1,
        UserGroupIds=[
            'mygroup'
        ],
        SecurityGroupIds=[
            'sg-7cc73803'
        ],
        CacheSubnetGroupName='default'

    )
    
    logging.info(response)
```

To run the program, enter the following command:

 `python ClusterModeEnabledWithRBAC.py`

For more information, see [Managing clusters in ElastiCache](Clusters.md).

### Check if users/usergroup exists, otherwise create them
<a name="ElastiCache-Getting-Started-Tutorials-Users"></a>

With RBAC, you create users and assign them specific permissions by using an access string. You assign the users to user groups aligned with a specific role (administrators, human resources) that are then deployed to one or more ElastiCache for Redis OSS replication groups. By doing this, you can establish security boundaries between clients using the same Valkey or Redis OSS replication group or groups and prevent clients from accessing each other’s data. For more information, see [Role-Based Access Control (RBAC)](Clusters.RBAC.md).

Copy the following program and paste it into a file named *UserAndUserGroups.py*. Update the mechanism for supplying credentials. Credentials in this example are shown as replaceable and assigned an undeclared item. Avoid hard-coding credentials.

This example uses an access string with the permissions for the user. For more information on access strings see [Specifying Permissions Using an Access String](Clusters.RBAC.md#Access-string).

```
import boto3
import logging

logging.basicConfig(level=logging.INFO)
client = boto3.client('elasticache')

def check_user_exists(UserId):
    """Checks if UserId exists

    Returns True if UserId exists, otherwise False
    :param UserId: ElastiCache User ID
    :return: True|False
    """
    try:
        response = client.describe_users(
            UserId=UserId,
        )
        if response['Users'][0]['UserId'].lower() == UserId.lower():
            return True
    except Exception as e:
        if e.response['Error']['Code'] == 'UserNotFound':
            logging.info(e.response['Error'])
            return False
        else:
            raise

def check_group_exists(UserGroupId):
    """Checks if UserGroupID exists

    Returns True if Group ID exists, otherwise False
    :param UserGroupId: ElastiCache User ID
    :return: True|False
    """

    try:
        response = client.describe_user_groups(
            UserGroupId=UserGroupId
        )
        if response['UserGroups'][0]['UserGroupId'].lower() == UserGroupId.lower():
            return True
    except Exception as e:
        if e.response['Error']['Code'] == 'UserGroupNotFound':
            logging.info(e.response['Error'])
            return False
        else:
            raise

def create_user(UserId=None,UserName=None,Password=None,AccessString=None):
    """Creates a new user

    Returns the ARN for the newly created user or the error message
    :param UserId: ElastiCache user ID. User IDs must be unique
    :param UserName: ElastiCache user name. ElastiCache allows multiple users with the same name as long as the associated user ID is unique.
    :param Password: Password for user. Must have at least 16 chars.
    :param AccessString: Access string with the permissions for the user. 
    :return: user ARN
    """
    try:
        response = client.create_user(
            UserId=UserId,
            UserName=UserName,
            Engine='Redis',
            Passwords=[Password],
            AccessString=AccessString,
            NoPasswordRequired=False
        )
        return response['ARN']
    except Exception as e:
        logging.info(e.response['Error'])
        return e.response['Error']

def create_group(UserGroupId=None, UserIds=None):
    """Creates a new group.
    A default user is required (mandatory) and should be specified in the UserIds list

    Return: Group ARN
    :param UserIds: List with user IDs to be associated with the new group. A default user is required
    :param UserGroupId: The ID (name) for the group
    :return: Group ARN
    """
    try:
        response = client.create_user_group(
            UserGroupId=UserGroupId,
            Engine='Redis',
            UserIds=UserIds
        )
        return response['ARN']
    except Exception as e:
        logging.info(e.response['Error'])


if __name__ == '__main__':
    
    groupName='mygroup2'
    userName = 'myuser2'
    userId=groupName+'-'+userName

    # Creates a new user if the user ID does not exist.
    for tmpUserId,tmpUserName in [ (userId,userName), (groupName+'-default','default')]:
        if not check_user_exists(tmpUserId):
            response=create_user(UserId=tmpUserId, UserName=EXAMPLE,Password=EXAMPLE,AccessString='on ~* +@all')
            logging.info(response)
        # assigns the new user ID to the user group
    if not check_group_exists(groupName):
        UserIds = [ userId , groupName+'-default']
        response=create_group(UserGroupId=groupName,UserIds=UserIds)
        logging.info(response)
```

To run the program, enter the following command:

 `python UserAndUserGroups.py`

## Tutorial: Connecting to ElastiCache
<a name="ElastiCache-Getting-Started-Tutorials-Connecting"></a>

The following examples use the Valkey or Redis OSS client to connect to ElastiCache.

**Topics**
+ [

### Connecting to a cluster mode disabled cluster
](#ElastiCache-Getting-Started-Tutorials-Connecting-cluster-mode-disabled)
+ [

### Connecting to a cluster mode enabled cluster
](#ElastiCache-Getting-Started-Tutorials-Connecting-cluster-mode-enabled)

### Connecting to a cluster mode disabled cluster
<a name="ElastiCache-Getting-Started-Tutorials-Connecting-cluster-mode-disabled"></a>

Copy the following program and paste it into a file named *ConnectClusterModeDisabled.py*. Update the mechanism for supplying credentials. Credentials in this example are shown as replaceable and assigned an undeclared item. Avoid hard-coding credentials.

```
from redis import Redis
import logging

logging.basicConfig(level=logging.INFO)
redis = Redis(host='primary.xxx.yyyyyy.zzz1.cache.amazonaws.com', port=6379, decode_responses=True, ssl=True, username=example, password=EXAMPLE)

if redis.ping():
    logging.info("Connected to Redis")
```

To run the program, enter the following command:

 `python ConnectClusterModeDisabled.py`

### Connecting to a cluster mode enabled cluster
<a name="ElastiCache-Getting-Started-Tutorials-Connecting-cluster-mode-enabled"></a>

Copy the following program and paste it into a file named *ConnectClusterModeEnabled.py*.

```
from rediscluster import RedisCluster
import logging

logging.basicConfig(level=logging.INFO)
redis = RedisCluster(startup_nodes=[{"host": "xxx.yyy.clustercfg.zzz1.cache.amazonaws.com","port": "6379"}], decode_responses=True,skip_full_coverage_check=True)

if redis.ping():
    logging.info("Connected to Redis")
```

To run the program, enter the following command:

 `python ConnectClusterModeEnabled.py`

## Usage examples
<a name="ElastiCache-Getting-Started-Tutorials-Usage"></a>

The following examples use the boto3 SDK for ElastiCache to work with ElastiCache for Redis OSS.

**Topics**
+ [

### Set and Get strings
](#ElastiCache-Getting-Started-Tutorials-set-strings)
+ [

### Set and Get a hash with multiple items
](#ElastiCache-Getting-Started-Tutorials-set-hash)
+ [

### Publish (write) and subscribe (read) from a Pub/Sub channel
](#ElastiCache-Getting-Started-Tutorials-pub-sub)
+ [

### Write and read from a stream
](#ElastiCache-Getting-Started-Tutorials-read-write-stream)

### Set and Get strings
<a name="ElastiCache-Getting-Started-Tutorials-set-strings"></a>

Copy the following program and paste it into a file named *SetAndGetStrings.py*.

```
import time
import logging
logging.basicConfig(level=logging.INFO,format='%(asctime)s: %(message)s')

keyName='mykey'
currTime=time.ctime(time.time())

# Set the key 'mykey' with the current date and time as value. 
# The Key will expire and removed from cache in 60 seconds.
redis.set(keyName, currTime, ex=60)

# Sleep just for better illustration of TTL (expiration) value
time.sleep(5)

# Retrieve the key value and current TTL
keyValue=redis.get(keyName)
keyTTL=redis.ttl(keyName)

logging.info("Key {} was set at {} and has {} seconds until expired".format(keyName, keyValue, keyTTL))
```

To run the program, enter the following command:

 `python SetAndGetStrings.py`

### Set and Get a hash with multiple items
<a name="ElastiCache-Getting-Started-Tutorials-set-hash"></a>

Copy the following program and paste it into a file named *SetAndGetHash.py*.

```
import logging
import time

logging.basicConfig(level=logging.INFO,format='%(asctime)s: %(message)s')

keyName='mykey'
keyValues={'datetime': time.ctime(time.time()), 'epochtime': time.time()}

# Set the hash 'mykey' with the current date and time in human readable format (datetime field) and epoch number (epochtime field). 
redis.hset(keyName, mapping=keyValues)

# Set the key to expire and removed from cache in 60 seconds.
redis.expire(keyName, 60)

# Sleep just for better illustration of TTL (expiration) value
time.sleep(5)

# Retrieves all the fields and current TTL
keyValues=redis.hgetall(keyName)
keyTTL=redis.ttl(keyName)

logging.info("Key {} was set at {} and has {} seconds until expired".format(keyName, keyValues, keyTTL))
```

To run the program, enter the following command:

 `python SetAndGetHash.py`

### Publish (write) and subscribe (read) from a Pub/Sub channel
<a name="ElastiCache-Getting-Started-Tutorials-pub-sub"></a>

Copy the following program and paste it into a file named *PubAndSub.py*.

```
import logging
import time

def handlerFunction(message):
    """Prints message got from PubSub channel to the log output

    Return None
    :param message: message to log
    """
    logging.info(message)

logging.basicConfig(level=logging.INFO)
redis = Redis(host="redis202104053.tihewd.ng.0001.use1.cache.amazonaws.com", port=6379, decode_responses=True)


# Creates the subscriber connection on "mychannel"
subscriber = redis.pubsub()
subscriber.subscribe(**{'mychannel': handlerFunction})

# Creates a new thread to watch for messages while the main process continues with its routines
thread = subscriber.run_in_thread(sleep_time=0.01)

# Creates publisher connection on "mychannel"
redis.publish('mychannel', 'My message')

# Publishes several messages. Subscriber thread will read and print on log.
while True:
    redis.publish('mychannel',time.ctime(time.time()))
    time.sleep(1)
```

To run the program, enter the following command:

 `python PubAndSub.py`

### Write and read from a stream
<a name="ElastiCache-Getting-Started-Tutorials-read-write-stream"></a>

Copy the following program and paste it into a file named *ReadWriteStream.py*.

```
from redis import Redis
import redis.exceptions as exceptions
import logging
import time
import threading

logging.basicConfig(level=logging.INFO)

def writeMessage(streamName):
    """Starts a loop writting the current time and thread name to 'streamName'

    :param streamName: Stream (key) name to write messages.
    """
    fieldsDict={'writerId':threading.currentThread().getName(),'myvalue':None}
    while True:
        fieldsDict['myvalue'] = time.ctime(time.time())
        redis.xadd(streamName,fieldsDict)
        time.sleep(1)

def readMessage(groupName=None,streamName=None):
    """Starts a loop reading from 'streamName'
    Multiple threads will read from the same stream consumer group. Consumer group is used to coordinate data distribution.
    Once a thread acknowleges the message, it won't be provided again. If message wasn't acknowledged, it can be served to another thread.

    :param groupName: stream group were multiple threads will read.
    :param streamName: Stream (key) name where messages will be read.
    """

    readerID=threading.currentThread().getName()
    while True:
        try:
            # Check if the stream has any message
            if redis.xlen(streamName)>0:
                # Check if if the messages are new (not acknowledged) or not (already processed)
                streamData=redis.xreadgroup(groupName,readerID,{streamName:'>'},count=1)
                if len(streamData) > 0:
                    msgId,message = streamData[0][1][0]
                    logging.info("{}: Got {} from ID {}".format(readerID,message,msgId))
                    #Do some processing here. If the message has been processed sucessfuly, acknowledge it and (optional) delete the message.
                    redis.xack(streamName,groupName,msgId)
                    logging.info("Stream message ID {} read and processed successfuly by {}".format(msgId,readerID))
                    redis.xdel(streamName,msgId)
            else:
                pass
        except:
            raise
            
        time.sleep(0.5)

# Creates the stream 'mystream' and consumer group 'myworkergroup' where multiple threads will write/read.
try:
    redis.xgroup_create('mystream','myworkergroup',mkstream=True)
except exceptions.ResponseError as e:
    logging.info("Consumer group already exists. Will continue despite the error: {}".format(e))
except:
    raise

# Starts 5 writer threads.
for writer_no in range(5):
    writerThread = threading.Thread(target=writeMessage, name='writer-'+str(writer_no), args=('mystream',),daemon=True)
    writerThread.start()

# Starts 10 reader threads
for reader_no in range(10):
    readerThread = threading.Thread(target=readMessage, name='reader-'+str(reader_no), args=('myworkergroup','mystream',),daemon=True)
    readerThread.daemon = True
    readerThread.start()

# Keep the code running for 30 seconds
time.sleep(30)
```

To run the program, enter the following command:

 `python ReadWriteStream.py`

# Tutorial: Configuring Lambda to access ElastiCache in a VPC
<a name="LambdaRedis"></a>

In this tutorial you can learn how to create an ElastiCache serverless cache, create a Lambda function, then test the Lambda function, and optionally clean up after.

**Topics**
+ [

## Step 1: Creating an ElastiCache serverless cache.
](#LambdaRedis.step1)
+ [

## Step 2: Create a Lambda function for ElastiCache
](#LambdaRedis.step2)
+ [

## Step 3: Test the Lambda function with ElastiCache
](#LambdaRedis.step3)
+ [

## Step 4: Clean up (Optional)
](#LambdaRedis.step4)

## Step 1: Creating an ElastiCache serverless cache.
<a name="LambdaRedis.step1"></a>

To create a serverless cache, follow these steps.

### Step 1.1: Create a serverless cache
<a name="LambdaRedis.step1.1"></a>

In this step, you create a serverless cache in the default Amazon VPC in the us-east-1 region in your account using the AWS Command Line Interface (CLI). For information on creating serverless cache using the ElastiCache console or API, see [Create a Redis OSS serverless cache](GettingStarted.serverless-redis.step1.md).

```
aws elasticache create-serverless-cache \
  --serverless-cache-name cache-01  \
--description "ElastiCache IAM auth application" \
--engine valkey
```

Note that the value of the Status field is set to `CREATING`. ElastiCache creates your cache in about a minute.

### Step 1.2: Copy serverless cache endpoint
<a name="LambdaRedis.step1.2"></a>

Verify that ElastiCache for Redis OSS has finished creating the cache with the `describe-serverless-caches` command.

```
aws elasticache describe-serverless-caches \
--serverless-cache-name cache-01
```

Copy the Endpoint Address shown in the output. You'll need this address when you create the deployment package for your Lambda function.

### Step 1.3: Create IAM Role
<a name="LambdaRedis.step1.3"></a>



1. Create an IAM trust policy document, as shown below, for your role that allows your account to assume the new role. Save the policy to a file named *trust-policy.json*.

------
#### [ JSON ]

****  

   ```
   {
   "Version":"2012-10-17",		 	 	 
       "Statement": [{
           "Effect": "Allow",
           "Action": "sts:AssumeRole",
           "Resource": "arn:aws:iam::*:role/*"
       },
       {
         "Effect": "Allow",
         "Action": "sts:AssumeRole",
         "Resource": "arn:aws:iam::*:role/*"
       }]
   }
   ```

------

1. Create an IAM policy document, as shown below. Save the policy to a file named *policy.json*.

------
#### [ JSON ]

****  

   ```
   {
   "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
   "Effect" : "Allow",
         "Action" : [
           "elasticache:Connect"
         ],
         "Resource" : [
           "arn:aws:elasticache:us-east-1:123456789012:serverlesscache:cache-01",
           "arn:aws:elasticache:us-east-1:123456789012:user:iam-user-01"
         ]
       }
     ]
   }
   ```

------

1. Create an IAM role.

   ```
   aws iam create-role \
   --role-name "elasticache-iam-auth-app" \
   --assume-role-policy-document file://trust-policy.json
   ```

1. Create the IAM policy.

   ```
   aws iam create-policy \
     --policy-name "elasticache-allow-all" \
     --policy-document file://policy.json
   ```

1. Attach the IAM policy to the role.

   ```
   aws iam attach-role-policy \
    --role-name "elasticache-iam-auth-app" \
    --policy-arn "arn:aws:iam::123456789012:policy/elasticache-allow-all"
   ```

### Step 1.4: Create a default user
<a name="LambdaRedis.step1.4"></a>

1. Create a new default user.

   ```
   aws elasticache create-user \
     --user-name default \
   --user-id default-user-disabled \
   --engine redis \
   --authentication-mode Type=no-password-required \
   --access-string "off +get ~keys*"
   ```

1. Create a new IAM-enabled user.

   ```
   aws elasticache create-user \
     --user-name iam-user-01 \
   --user-id iam-user-01 \
   --authentication-mode Type=iam \
   --engine redis \
   --access-string "on ~* +@all"
   ```

1. Create a user group and attach the user.

   ```
   aws elasticache create-user-group \
     --user-group-id iam-user-group-01 \
   --engine redis \
   --user-ids default-user-disabled iam-user-01
   
   aws elasticache modify-serverless-cache \
     --serverless-cache-name cache-01  \
   --user-group-id iam-user-group-01
   ```

## Step 2: Create a Lambda function for ElastiCache
<a name="LambdaRedis.step2"></a>

To create a Lambda function to access the ElastiCache cache, take these steps.

### Step 2.1: Create a Lambda function
<a name="LambdaRedis.step2.1"></a>

In this tutorial, we provide example code in Python for your Lambda function.

**Python**

The following example Python code reads and writes an item to your ElastiCache cache. Copy the code and save it into a file named `app.py`. Be sure to replace the `elasticache_endpoint` value in the code with the endpoint address you copied in the previous step. 

```
from typing import Tuple, Union
from urllib.parse import ParseResult, urlencode, urlunparse

import botocore.session
import redis
from botocore.model import ServiceId
from botocore.signers import RequestSigner
from cachetools import TTLCache, cached
import uuid

class ElastiCacheIAMProvider(redis.CredentialProvider):
    def __init__(self, user, cache_name, is_serverless=False, region="us-east-1"):
        self.user = user
        self.cache_name = cache_name
        self.is_serverless = is_serverless
        self.region = region

        session = botocore.session.get_session()
        self.request_signer = RequestSigner(
            ServiceId("elasticache"),
            self.region,
            "elasticache",
            "v4",
            session.get_credentials(),
            session.get_component("event_emitter"),
        )

    # Generated IAM tokens are valid for 15 minutes
    @cached(cache=TTLCache(maxsize=128, ttl=900))
    def get_credentials(self) -> Union[Tuple[str], Tuple[str, str]]:
        query_params = {"Action": "connect", "User": self.user}
        if self.is_serverless:
            query_params["ResourceType"] = "ServerlessCache"
        url = urlunparse(
            ParseResult(
                scheme="https",
                netloc=self.cache_name,
                path="/",
                query=urlencode(query_params),
                params="",
                fragment="",
            )
        )
        signed_url = self.request_signer.generate_presigned_url(
            {"method": "GET", "url": url, "body": {}, "headers": {}, "context": {}},
            operation_name="connect",
            expires_in=900,
            region_name=self.region,
        )
        # RequestSigner only seems to work if the URL has a protocol, but
        # Elasticache only accepts the URL without a protocol
        # So strip it off the signed URL before returning
        return (self.user, signed_url.removeprefix("https://"))

def lambda_handler(event, context):
    username = "iam-user-01" # replace with your user id
    cache_name = "cache-01" # replace with your cache name
    elasticache_endpoint = "cache-01-xxxxx.serverless.use1.cache.amazonaws.com" # replace with your cache endpoint
    creds_provider = ElastiCacheIAMProvider(user=username, cache_name=cache_name, is_serverless=True)
    redis_client = redis.Redis(host=elasticache_endpoint, port=6379, credential_provider=creds_provider, ssl=True, ssl_cert_reqs="none")
    
    key='uuid'
    # create a random UUID - this will be the sample element we add to the cache
    uuid_in = uuid.uuid4().hex
    redis_client.set(key, uuid_in)
    result = redis_client.get(key)
    decoded_result = result.decode("utf-8")
    # check the retrieved item matches the item added to the cache and print
    # the results
    if decoded_result == uuid_in:
        print(f"Success: Inserted {uuid_in}. Fetched {decoded_result} from Valkey.")
    else:
        raise Exception(f"Bad value retrieved. Expected {uuid_in}, got {decoded_result}")
        
    return "Fetched value from Valkey"
```

This code uses the Python redis-py library to put items into your cache and retrieve them. This code uses cachetools to cache generated IAM Auth tokens for 15 mins. To create a deployment package containing redis-py and cachetools, carry out the following steps.

In your project directory containing the app.py source code file, create a folder package to install the redis-py and cachetools libraries into.

```
mkdir package
```

Install redis-py, cachetools using pip.

```
pip install --target ./package redis
pip install --target ./package cachetools
```

Create a .zip file containing the redis-py and cachetools libraries. In Linux and macOS, run the following command. In Windows, use your preferred zip utility to create a .zip file with the redis-py and cachetools libraries at the root.

```
cd package
zip -r ../my_deployment_package.zip .
```

Add your function code to the .zip file. In Linux and macOS, run the following command. In Windows, use your preferred zip utility to add app.py to the root of your .zip file.

```
cd ..
zip my_deployment_package.zip app.py
```

### Step 2.2: Create the IAM role (execution role)
<a name="LambdaRedis.step2.2"></a>

Attach the AWS managed policy named `AWSLambdaVPCAccessExecutionRole` to the role.

```
aws iam attach-role-policy \
 --role-name "elasticache-iam-auth-app" \
 --policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
```

### Step 2.3: Upload the deployment package (create the Lambda function)
<a name="LambdaRedis.step2.3"></a>

In this step, you create the Lambda function (AccessValkey) using the create-function AWS CLI command. 

From the project directory that contains your deployment package .zip file, run the following Lambda CLI `create-function` command.

For the role option, use the ARN of the execution role you created in the previous step. For the vpc-config enter comma separated lists of your default VPC's subnets and your default VPC's security group ID. You can find these values in the Amazon VPC console. To find your default VPC's subnets, choose **Your VPCs**, then choose your AWS account's default VPC. To find the security group for this VPC, go to **Security** and choose **Security groups**. Ensure that you have the us-east-1 region selected.

```
aws lambda create-function \
--function-name AccessValkey  \
--region us-east-1 \
--zip-file fileb://my_deployment_package.zip \
--role arn:aws:iam::123456789012:role/elasticache-iam-auth-app \
--handler app.lambda_handler \
--runtime python3.12  \
--timeout 30 \
--vpc-config SubnetIds=comma-separated-vpc-subnet-ids,SecurityGroupIds=default-security-group-id
```

## Step 3: Test the Lambda function with ElastiCache
<a name="LambdaRedis.step3"></a>

In this step, you invoke the Lambda function manually using the invoke command. When the Lambda function executes, it generates a UUID and writes it to the ElastiCache cache that you specified in your Lambda code. The Lambda function then retrieves the item from the cache.

1. Invoke the Lambda function (AccessValkey) using the AWS Lambda invoke command.

   ```
   aws lambda invoke \
   --function-name AccessValkey  \
   --region us-east-1 \
   output.txt
   ```

1. Verify that the Lambda function executed successfully as follows:
   + Review the output.txt file.
   + Verify the results in CloudWatch Logs by opening the CloudWatch console and choosing the log group for your function (/aws/lambda/AccessValkey). The log stream should contain output similar to the following:

     ```
     Success: Inserted 826e70c5f4d2478c8c18027125a3e01e. Fetched 826e70c5f4d2478c8c18027125a3e01e from Valkey.
     ```
   + Review the results in the AWS Lambda console.

## Step 4: Clean up (Optional)
<a name="LambdaRedis.step4"></a>

To clean up, take these steps.

### Step 4.1: Delete Lambda function
<a name="LambdaRedis.step4.1"></a>

```
aws lambda delete-function \
 --function-name AccessValkey
```

### Step 4.2: Delete Serverless cache
<a name="LambdaRedis.step4.2"></a>

Delete the cache.

```
aws elasticache delete-serverless-cache \
 --serverless-cache-name cache-01
```

Remove users and user group.

```
aws elasticache delete-user \
 --user-id default-user-disabled

aws elasticache delete-user \
 --user-id iam-user-01

aws elasticache delete-user-group \
 --user-group-id iam-user-group-01
```

### Step 4.3: Remove IAM Role and policies
<a name="LambdaRedis.step4.3"></a>

```
aws iam detach-role-policy \
 --role-name "elasticache-iam-auth-app" \
 --policy-arn "arn:aws:iam::123456789012:policy/elasticache-allow-all"
 
aws iam detach-role-policy \
--role-name "elasticache-iam-auth-app" \
--policy-arn "arn:aws:iam::aws:policy/service-role/AWSLambdaVPCAccessExecutionRole"
 
aws iam delete-role \
 --role-name "elasticache-iam-auth-app"
  
 aws iam delete-policy \
  --policy-arn "arn:aws:iam::123456789012:policy/elasticache-allow-all"
```