---
title: Event batching for the Android SDK
slug: feature-experimentation/docs/event-batching-android
docTags: 
createdAt: 2026-08-05T20:39:55.000Z
---

The Android SDK lets you batch events and includes options to set an event batch size, event time interval and event flush interval. The benefit of event batching is less network traffic for the same number of impression and conversion events tracked.

In the Android SDK, `BatchEventProcessor` provides the implementation of the `EventProcessor` interface and batches events. You can control batching based on two parameters:

- **Batch size** – Defines the number of batched events before sending to Optimizely Feature Experimentation.
- **Flush interval** – Defines the amount of time after which any batched events should be passed to the Event Dispatcher to be sent to Optimizely.

An event consisting of the batched payload is sent when the batch size reaches the specified limit or the flush interval reaches the specified time limit. `BatchEventProcessor` options are described in the following sections.

:::hint{type="info"}
**Note**
The default [Event Dispatcher](docId\:w7doPrWnB8BSibrBAYkWK) in the Android SDK uses Android [WorkManager](https://developer.android.com/topic/libraries/architecture/workmanager) to dispatch batched requests. As a result you may observe additional delays to outbound requests beyond your specified flush interval as a result of system limits on those requests.

Event batching works with both out-of-the-box and custom event dispatchers.

The event batching process does not remove any personally identifiable information (PII) from events. You must still ensure that you are not sending any unnecessary PII to Optimizely.
:::

## Basic example

```kotlin
val optimizelyManager = OptimizelyManager.builder()
         .withSDKKey("<Your_SDK_Key>")
         .build(context)
val optimizely = optimizelyManager.initialize(context, R.raw.datafile)
```

```java
OptimizelyManager optimizelyManager = OptimizelyManager.builder()
        .withSDKKey("<Your_SDK_Key>")
        .build(context);
OptimizelyClient optimizely = optimizelyManager.initialize(context, R.raw.datafile);
```

By default, batch size is 10 and flush interval is 30 seconds.

## Advanced Example

```kotlin
val eventHandler: EventHandler = DefaultEventHandler.getInstance(context)

// Here we are using the builder options to set batch size
// to 5 events and flush interval to a minute.
val batchProcessor = BatchEventProcessor.builder()
         .withBatchSize(5)
         .withEventHandler(eventHandler)
         .withFlushInterval(TimeUnit.MINUTES.toMillis(1L))
         .build()
val optimizelyManager = OptimizelyManager.builder()
         .withSDKKey("<Your_SDK_Key>")
         .withEventHandler(eventHandler)
         .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
         .withEventProcessor(batchProcessor)
         .build(context)
val optimizely = optimizelyManager.initialize(context, R.raw.datafile)
```

```java
EventHandler eventHandler = DefaultEventHandler.getInstance(context);

// Here we are using the builder options to set batch size
// to 5 events and flush interval to a minute.
BatchEventProcessor batchProcessor = BatchEventProcessor.builder()
         .withBatchSize(5)
         .withEventHandler(eventHandler)
         .withFlushInterval(TimeUnit.MINUTES.toMillis(1L))
         .build();

OptimizelyManager optimizelyManager = OptimizelyManager.builder()
         .withSDKKey("<Your_SDK_Key>")
         .withEventHandler(eventHandler)
         .withDatafileDownloadInterval(15, TimeUnit.MINUTES)
         .withEventProcessor(batchProcessor)
         .build(context);

OptimizelyClient optimizely = optimizelyManager.initialize(context, R.raw.datafile);
```

:::hint{type="danger"}
**Warning**
The maximum payload size is 3.5 MB. Optimizely rejects requests with a 400 response code, `Bad Request Error`, if the batch payload exceeds this limit.

The size limitation is because of the [Optimizely Events API](docId:822ZQOB6Zk2-kWJKavBvA), which is used to send data to Optimizely.

The most common cause of a large payload size is a high batch size. If your payloads exceed the size limit, try configuring a smaller batch size.
:::

## BatchEventProcessor

`BatchEventProcessor` is an implementation of `EventProcessor` where events are batched. The class maintains a single consumer thread that pulls events off of the `BlockingQueue` and buffers them for either a configured batch size or a maximum duration before the resulting `LogEvent` is sent to the `EventDispatcher` and `NotificationCenter`.

The following properties can be used to customize the `BatchEventProcessor` configuration using the `Builder class`.

## Builder methods

Use the following methods to customize the `BatchEventProcessor`.

| Property                   | Default value          | Description                                                                                                                                                                                                |
| -------------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **withEventHandler**       | null                   | Required field. Specifies event handler to use to dispatch event payload to Optimizely. By default, if you create an Optimizely instance, it passes in \`DefaultEventHandler\` to \`BatchEventProcessor\`. |
| **withBatchSize**          | 10                     | The maximum number of events to batch before dispatching. Once this number is reached, all queued events are flushed and sent to Optimizely.                                                               |
| **withFlushInterval**      | 30000 (30 Seconds)     | Maximum time after which to batch and send event payload to Optimizely. In milliseconds.                                                                                                                   |
| **withEventQueue**         | 1000                   | BlockingQueue that queues individual events to be batched and dispatched by the executor.                                                                                                                  |
| **withNotificationCenter** | null                   | Notification center instance to be used to trigger any notifications to notify when event batches are flushed.                                                                                             |
| **withExecutor**           | Single Thread Executor | Executor service that takes care of triggering event batching and subsequent dispatching to Optimizely.                                                                                                    |
| **withTimeout**            | 5000                   | Maximum time to wait for event processor’s close to be executed. In milliseconds.                                                                                                                          |

## Advanced configuration

You can set the following properties to override the default configuration for `BatchEventProcessor`.

| Property                           | Default value | Description                                                                              |
| ---------------------------------- | ------------- | ---------------------------------------------------------------------------------------- |
| **event.processor.batch.size**     | 10            | Maximum size of batch of events to send to Optimizely.                                   |
| **event.processor.batch.interval** | 30000         | Maximum time after which to batch and send event payload to Optimizely. In milliseconds. |
| **event.processor.close.timeout**  | 5000          | Maximum time to wait for event processor’s close to be executed. In milliseconds.        |

For information, see [Initialize the Android SDK](docId\:yOiJjsSgQ1uieWHJkR42D).

## Side effects

The table lists other Optimizely functionality that may be triggered by using this class.

| Functionality          | Description                                                                                                                                                                                                                                                                                  |
| ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| \`LogEvent\`           | Whenever the event processor produces a batch of events, a \`LogEvent\` object is created using the \`EventFactory\`. It contains batch of conversion and decision events. This object is dispatched using the provided event dispatcher and also it is sent to the notification subscribers |
| Notification Listeners | Flush invokes the LOGEVENT \[notification listener]\(https\://docs.developers.optimizely.com/feature-experimentation/docs/set-up-notification-listener-android) if this listener is subscribed to.                                                                                           |

### Register `LogEvent` listener

To register a `LogEvent` notification listener:

```kotlin
optimizely.notificationCenter?.addNotificationHandler(LogEvent::class.java) { logEvent: LogEvent ->
    Log.d("Optimizely", "event dispatched: $logEvent")
}
```

```java
optimizely.getNotificationCenter().addNotificationHandler(LogEvent.class, logEvent -> {
    Log.d("Optimizely", "event dispatched: " + logEvent);
});
```

### `LogEvent`

`LogEvent` object gets created using [`EventFactory`](https://github.com/optimizely/java-sdk/blob/master/core-api/src/main/java/com/optimizely/ab/event/internal/EventFactory.java). It represents the batch of decision and conversion events Optimizely sends to the Optimizely backend.

| Object                                                                                                                                                                                       | Type                 | Description                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| **requestMethod** \*Required (non null)\*                                                                                                                                                    | RequestMethod (Enum) | The HTTP verb to use when dispatching the log event. It can be \`GET\` or \`POST\`.                                            |
| **endpointUrl**\ \*Required (non null)\*                                                                                                                                                     | String               | URL to dispatch log event to.                                                                                                  |
| **requestParams**\ \*Required (non null)\*                                                                                                                                                   | Map\\                | Parameters to be set in the log event.                                                                                         |
| \*\*\[eventBatch]\(https\://github.com/optimizely/java-sdk/blob/13c27ffc812928ef5cf05159d37ad6bab421fc5a/core-api/src/main/java/com/optimizely/ab/event/LogEvent.java#L38)\*\*\ \*Required\* | EventBatch           | It contains all the information regarding every event which is batched, including a list of visitors which contains UserEvent. |

## Close Optimizely on application exit

If you enable event batching, **you must call** the Close method (`optimizelyClient.close()`) before exiting. This ensures that queued events are flushed when possible to avoid data loss.

:::hint{type="info"}
**Warning**
Because the Optimizely client maintains a buffer of queued events, you must call `close()` on the Optimizely instance before shutting down your application or whenever dereferencing the instance.
:::

| Method      | Description                                                                                                                                                |
| ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **close()** | Stops event processing and flushes the event queue. On Android, background datafile updates run through WorkManager and continue after you call `close()`. |
