How to Temporarily Stop AWS Elasticsearch Service to Avoid Unnecessary Charges


3 views

Unlike EC2 instances that can be stopped when not in use, AWS Elasticsearch Service operates on a continuous billing model. Many developers discover this the hard way when they see unexpected charges for test environments that were only needed temporarily. The service is designed to maintain persistent clusters rather than offering start/stop functionality.

Elasticsearch clusters require persistent storage and maintain complex internal states. AWS engineering teams have explained that pausing these clusters would:

  • Require snapshotting all shard data and node states
  • Need to preserve exact cluster topology and configurations
  • Maintain security settings and IAM roles during the "stopped" period

Here are three approaches we've used successfully:

// Alternative 1: Scheduled Scaling with AWS Lambda
const AWS = require('aws-sdk');
const es = new AWS.ES();

exports.handler = async (event) => {
  const params = {
    DomainName: 'your-test-cluster',
    ElasticsearchClusterConfig: {
      InstanceType: 't2.small.elasticsearch',  // Downgrade when not testing
      InstanceCount: 1                        // Minimum nodes
    }
  };
  
  return es.updateElasticsearchDomainConfig(params).promise();
};

Create a CloudWatch Event that triggers during non-working hours:

Resources:
  ScaleDownElasticsearch:
    Type: AWS::Events::Rule
    Properties:
      ScheduleExpression: "cron(0 18 ? * MON-FRI *)"
      Targets:
        - Arn: !GetAtt ScaleDownLambda.Arn
          Id: "ScaleDownTarget"

For truly temporary testing environments, consider automating the creation and deletion process:

#!/bin/bash
# Create test environment
aws es create-elasticsearch-domain --domain-name temp-test-env \
  --elasticsearch-version 7.9 \
  --elasticsearch-cluster-config InstanceType=t3.medium.elasticsearch,InstanceCount=1

# Your testing commands here...

# Cleanup when done
aws es delete-elasticsearch-domain --domain-name temp-test-env

When working with AWS OpenSearch Service (formerly Amazon Elasticsearch Service), many developers discover that unlike EC2 instances which can be stopped when not in use, OpenSearch domains continue running 24/7 - and billing accordingly. This becomes particularly painful for:

  • Development and testing environments
  • Proof-of-concept implementations
  • Projects with intermittent search requirements

While AWS doesn't provide a simple "stop" button, here are practical approaches:

1. Scaling Down to Minimum Configuration

You can minimize costs by reducing your cluster to the smallest possible configuration:

aws opensearch update-domain-config --domain-name your-domain \
--cluster-config InstanceType=t3.small.search,InstanceCount=1 \
--ebs-options EBSEnabled=true,VolumeType=gp2,VolumeSize=10

This reduces costs to about $0.036/hour (for t3.small in us-east-1).

2. Scheduled Scaling with Lambda

For predictable usage patterns, implement automated scaling:

import boto3

def lambda_handler(event, context):
    client = boto3.client('opensearch')
    
    # Scale down at night
    response = client.update_domain_config(
        DomainName='dev-search',
        ClusterConfig={
            'InstanceType': 't3.small.search',
            'InstanceCount': 1
        }
    )
    
    return response

3. Snapshot and Delete (Most Cost-Effective)

For long periods of inactivity:

  1. Create manual snapshot to S3
  2. Delete the domain
  3. Restore from snapshot when needed
Option Cost Savings Recovery Time
Scaling Down ~80% Instant
Snapshot & Delete 100% 15-30 minutes

For development environments, consider:

  • Local Docker containers running OpenSearch
  • EC2 instances with self-managed OpenSearch (can be stopped)
  • Serverless solutions like AWS Lambda with DynamoDB for simple search needs