Google Cloud Platform

App Engine Modules in Java

Python |Java |PHP |Go

App Engine Modules (or just "Modules" hereafter) let developers factor large applications into logical components that can share stateful services and communicate in a secure fashion. A deployed module behaves like a microservice. By using multiple modules you can deploy your app as a set of microservices, which is a popular design pattern.

For example, an app that handles customer requests might include separate modules to handle other tasks, such as:

  • API requests from mobile devices
  • Internal, admin-like requests
  • Backend processing such as billing pipelines and data analysis

Modules can be configured to use different runtimes and to operate with different performance settings.

  1. Application hierarchy
  2. Scaling types and instance classes
  3. Configuration
  4. Uploading and deleting modules
  5. Instance states
  6. Instance uptime
  7. Background threads
  8. Monitoring resource usage
  9. Logging
  10. Communication between modules
  11. Limits

Application hierarchy

At the highest level, an App Engine application is made up of one or more modules. Each module consists of source code and configuration files. The files used by a module represent a version of the module. When you deploy a module, you always deploy a specific version of the module. For this reason, whenever we speak of a module, it usually means a version of a module.

You can deploy multiple versions of the same module, to account for alternative implementations or progressive upgrades as time goes on.

Each module and each version must have a name. A name can contain numbers, letters, and hyphens. It cannot be longer than 63 characters and cannot start or end with a hyphen. Choose a unique name for each module and each version. Don't reuse names between modules and versions.

While running, a particular module/version will have one or more instances. Each instance runs its own separate executable. The number of instances running at any time depends on the module's scaling type and the amount of incoming requests:

Hierarchy graph of modules/versions/instances

Stateful services (such as Memcache, Datastore, and Task Queues) are shared by all the modules in an application. Every module, version, and instance has its own unique URI (for example, Incoming user requests are routed to an instance of a particular module/version according to URL addressing conventions and an optional customized dispatch file.

Note: After April 2013 Google does not issue SSL certificates for double-wildcard domains hosted at (i.e. *.* If you rely on such URLs for HTTPS access to your application, change any application logic to use "-dot-" instead of ".". For example, to access version v1 of application myapp use The certificate will not match if you use, and an error occurs for any User-Agent that expects the URL and certificate to match exactly.

Scaling types and instance classes

When you upload a version of a module, the configuration file specifies a scaling type and instance class that apply to every instance of that version. The scaling type controls how instances are created. The instance class determines compute resources and pricing. There are three scaling types: manual, basic, and automatic. Available instance classes depend on the scaling type.

Scaling Type Description Available Instance Classes
Manual Scaling A module with manual scaling runs continuously, allowing you to perform complex initialization and rely on the state of its memory over time. B1, B2, B4, B4_1G, or B8
Basic Scaling A module with basic scaling will create an instance when the application receives a request. The instance will be turned down when the app becomes idle. Basic scaling is ideal for work that is intermittent or driven by user activity. B1, B2, B4, B4_1G, or B8
Automatic Scaling Automatic scaling is based on request rate, response latencies, and other application metrics. F1, F2, F4, or F4_1G

This table summarizes the CPU, memory, and hourly billing rate of the various instance classes.

Instance Class Memory Limit CPU Limit Cost per Hour per Instance
B1 128 MB 600 Mhz $0.05
B2 256 MB 1.2 Ghz $0.10
B4 512 MB 2.4 Ghz $0.20
B4_1G 1024 MB 2.4 Ghz $0.30
B8 1024 MB 4.8 Ghz $0.40
F1 128 MB 600 Mhz $0.05
F2 256 MB 1.2 Ghz $0.10
F4 512 MB 2.4 Ghz $0.20
F4_1G 1024 MB 2.4 Ghz $0.30

Instances running in manual and basic scaling modules are billed at hourly rates based on uptime. Billing begins when an instance starts and ends fifteen minutes after a manual instance shuts down or fifteen minutes after a basic instance has finished processing its last request. Runtime overhead is counted against the instance memory limit. This will be higher for Java than for other languages.

Important: When you are billed for instance hours, you will not see any instance classes in your billing line items. Instead, you will see the appropriate multiple of instance hours. For example, if you use an F4 instance for one hour, you do not see "F4" listed, but you will see billing for four instance hours at the F1 rate.

This table compares the performance features of the three scaling types:

Feature Automatic Scaling Manual Scaling Basic Scaling
Deadlines 60-second deadline for HTTP requests, 10-minute deadline for tasks Requests can run indefinitely. A manually-scaled instance can choose to handle /_ah/start and execute a program or script for many hours without returning an HTTP response code. Tasks can run up to 24 hours. Same as manual scaling.
Background Threads Not allowed Allowed Allowed
Residence Instances are evicted from memory based on usage patterns. Instances remain in memory, and state is preserved across requests. When instances are restarted, an /_ah/stop request appears in the logs. If there is a registered stop callback method, it has 30 seconds to complete before shutdown occurs. Instances are evicted based on the idle-timeout parameter. If an instance has been idle, i.e. has not received a request, for more than idle-timeout, then the instance is evicted.
Startup and Shutdown Instances are created on demand to handle requests and automatically turned down when idle. Instances are sent a start request automatically by App Engine in the form of an empty GET request to /_ah/start. An instance that is stopped with appcfg stop (or from the Cloud Platform Console) has 30 seconds to finish handling requests before it is forcibly terminated. Instances are created on demand to handle requests and automatically turned down when idle, based on the idle-timeout configuration parameter. As with manual scaling, an instance that is stopped with appcfg stop (or from the Cloud Platform Console) has 30 seconds to finish handling requests before it is forcibly terminated.
Instance Addressability Instances are anonymous. Instance "i" of version "v" of module "m" is addressable at the URL: If you have set up a wildcard subdomain mapping for a custom domain, you can also address a module or any of its instances via a URL of the form or You can reliably cache state in each instance and retrieve it in subsequent requests. Same as manual scaling.
Scaling App Engine scales the number of instances automatically in response to processing volume. This scaling factors in the automatic_scaling settings that are provided on a per-version basis in the configuration file uploaded with the module version. You configure the number of instances of each module version in that module’s configuration file. The number of instances usually corresponds to the size of a dataset being held in memory or the desired throughput for offline work. A basic scaling module version is configured with a maximum number of instances using the basic_scaling setting's max_instances parameter. The number of live instances scales with the processing volume.
Free Daily Usage Quota 28 instance-hours 8 instance-hours 8 instance-hours


An App Engine application that uses modules is organized as an unpacked Java Enterprise Archive (EAR) directory structure. The top-level EAR directory contains a single META-INF subdirectory, and a separate directory for each module in the app. These module directories are organized as unpacked Java Web Application Archives (WAR). Each WAR directory usually has the same name as the module it defines, but this is not required. Although Java EE supports WAR files, module configuration uses unpacked WAR directories only. App Engine's Java SDK includes an Apache Maven tool that can build a skeletal EAR structure for you.

Hierarchy graph of EAR directories

The META-INF directory has two configuration files: appengine-application.xml and application.xml. The appengine-application.xml file contains general information used by App Engine tools when your app is deployed. The application.xml file declares the list of modules and their WAR directories that comprise the application. The WAR directory for each module contains two configuration files: appengine-web.xml, and web.xml. General information on these files can be found in the Java Getting Started tutorial.

The WAR directory file appengine-web.xml defines the configuration of modules. Each module has its own file, which defines the scaling type and instance class for a specific module/version. Different scaling parameters are used depending on which type of scaling you specify. If you do not specify scaling, automatic scaling is the default.

Note that while every appengine-web.xml file must contain the <application> tag, the name you supply there is ignored. The name of the application is taken from the <application> tag in the appengine-application.xml file.

For each module you can also specify settings that map URL requests to specific Java servlets and identify static files for better server efficiency. These settings are included in the web.xml and appengine-web.xml files and are described in the Deployment Descriptor and App Config sections.

The default module

Every application has a single default module. The default module is defined by the standard appengine-web.xml file or by an appengine-web.xml with the setting <module>default</module>. All configuration parameters relevant to modules can apply to the default module.

Also be sure to list the default module as the first module in the EAR directory's META-INF/application.xml file, as shown in the example below.

Optional configuration files

These configuration files control optional features that apply to all the modules in an app:

  • dispatch.xml
  • queue.xml
  • datastore-indexes.xml
  • cron.xml
  • dos.xml

If you use any of these files, put them in the default module's WEB-INF directory.

An example

Here is an example of how you would configure the various files in an EAR directory structure for an application that has two modules: a default module that handles web requests, plus another module (named my-module) for backend processing.

Assuming that the top-level EAR directory is "my-application," define the file my-application/META-INF/appengine-application.xml:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<appengine-application xmlns="">

Create WAR directories for the two modules: my-application/default and my-application/my-module.

Now create an appengine-web.xml file in each WAR that specifies the parameters for the module. The file must include a version name for the module. To define the default module, you can explicitly include the <module>default</module> parameter or leave it out of the file. Here is the file my-application/default/WEB-INF/appengine-web.xml that defines the default module:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<appengine-web-app xmlns="">

The file my-application/my-module/WEB-INF/appengine-web.xml defines the module that will handle background requests:

<?xml version="1.0" encoding="utf-8" standalone="no"?>
<appengine-web-app xmlns="">

Finally, define the file my-application/META-INF/application.xml that enumerates the modules. Note that the default module should be the first module listed.

<?xml version="1.0"


  <description>GAE Java SuperFun app</description>

  <!-- Modules -->
  <!-- The default module should be listed first -->


App Engine will ignore the <context-root> elements, so HTTP clients need not prepend it to the URL path when addressing a module.

Uploading and deleting modules

To deploy the example above, use the appcfg update command, passing the directory path of the EAR:

appcfg update <directory-path>

To only upload a specific module, give the directory path for its WAR: update <directory-path>/my-application/my-module

If you are uploading the app for the first time, you must either pass the EAR path, or upload the WAR directory for the default module first.

You will receive verification via the command line as each module is successfully deployed. Once the application has been deployed you can access it at

Similarly, you can access each of the modules individually:


If you run multiple versions of a module, you can access a specific version by prepending the version name to the URI. For example, will target version uno of the default module. Routing Requests to Modules explains addressing module instances in detail.

Instance states

A manual or basic scaled instance can be in one of two states: Running or Stopped. All instances of a particular module/version share the same state. You can change the state of all the instances belonging to a module/version using the appcfg command or the Modules API.


Each module instance is created in response to a start request, which is an empty GET request to /_ah/start. App Engine sends this request to bring an instance into existence; users cannot send a request to /_ah/start. Manual and basic scaling instances must respond to the start request before they can handle another request. The start request can be used for two purposes:

  • To start a program that runs indefinitely, without accepting further requests
  • To initialize an instance before it receives additional traffic

Manual, basic, and automatically scaling instances startup differently. When you start a manual scaling instance, App Engine immediately sends a /_ah/start request to each instance. When you start an instance of a basic scaling module, App Engine allows it to accept traffic, but the /_ah/start request is not sent to an instance until it receives its first user request. Multiple basic scaling instances are only started as necessary, in order to handle increased traffic. Automatically scaling instances do not receive any /_ah/start request.

When an instance responds to the /_ah/start request with an HTTP status code of 200–299 or 404, it is considered to have successfully started and can handle additional requests. Otherwise, App Engine terminates the instance. Manual scaling instances are restarted immediately, while basic scaling instances are restarted only when needed for serving traffic.


The shutdown process may be triggered by a variety of planned and unplanned events, such as:

  • You manually stop an instance using the appcfg stop command or the Modules API stopVersion function call.
  • Manually stop an instance from the Cloud Platform Console Instances page.
  • You update the module version using appcfg update.
  • The instance exceeds the maximum memory for its configured instance_class.
  • Your application runs out of Instance Hours quota.
  • The machine running the instance is restarted, forcing your instance to move to a different machine.
  • App Engine needs to move your instance to a different machine to improve load distribution.

The following code sample demonstrates a basic shutdown hook:

LifecycleManager.getInstance().setShutdownHook(new ShutdownHook() {
  public void shutdown() {

Alternatively, the following sample demonstrates how to use the isShuttingDown() method:

while (haveMoreWork()
&& !LifecycleManager.getInstance().isShuttingDown()) {

Instance uptime

App Engine attempts to keep manual and basic scaling instances running indefinitely. However, at this time there is no guaranteed uptime for manual and basic scaling instances. Hardware and software failures that cause early termination or frequent restarts can occur without prior warning and may take considerable time to resolve; thus, you should construct your application in a way that tolerates these failures. The App Engine team will provide more guidance on expected instance uptime as statistics become available.

Here are some good strategies for avoiding downtime due to instance restarts:

  • Use load balancing across multiple instances.
  • Configure more instances than are normally required to handle your traffic patterns.
  • Write fall-back logic that uses cached results when a manual scaling instance is unavailable.
  • Reduce the amount of time it takes for your instances to start up and shutdown.
  • Duplicate the state information across more than one instance.
  • For long-running computations, checkpoint the state from time to time so you can resume it if it doesn't complete.

It's also important to recognize that the shutdown hook is not always able to run before an instance terminates. In rare cases, an outage can occur that prevents App Engine from providing 30 seconds of shutdown time. Thus, we recommend periodically checkpointing the state of your instance and using it primarily as an in-memory cache rather than a reliable data store.

Background threads

Code running on a manual scaling instance can start a background thread that may outlive the request that spawns it. This allows instances to perform arbitrary periodic or scheduled tasks or to continue working in the background after a request has returned to the user.

A background thread's logging entries are independent of those of the spawning thread. You can read more about background threads in App Engine's ThreadManager documentation.

import java.util.concurrent.atomic.AtomicLong;

AtomicLong counter = new AtomicLong();

Thread thread = ThreadManager.createBackgroundThread(new Runnable() {
  public void run() {
    try {
      while (true) {
    } catch (InterruptedException ex) {
      throw new RuntimeException("Interrupted in loop:", ex);

If code running in an automatic scaling module attempts to start a background thread, it raises an exception.

The maximum number of concurrent background threads is 10 per instance.

Monitoring resource usage

The Instances page of the Cloud Platform Console provides visibility into how instances are performing. By selecting your module and version in the dropdowns, you can see the memory and CPU usage of each instance, uptime, number of requests, and other statistics. You can also manually initiate the shutdown process for any instance.

You also can use the Runtime API to access statistics showing the CPU and memory usage of your instances. These statistics help you understand how resource usage responds to requests or work performed, and also how to regulate the amount of data stored in memory in order to stay below the memory limit of your instance class.


You can use the Logs API to access your app's request and application logs. In particular, the fetch() function allows you to retrieve logs using various filters, such as request ID, timestamp, module ID, and version ID.

Application (user/app-generated) logs are periodically flushed while manual and basic scaling instances handle requests; since modules can run on a request a long time, logs may not flush for a while. You can tune the flush settings, or force an immediate flush, using the Logs API. When a flush occurs, a new log entry is created at the time of the flush, containing any log messages that have not yet been flushed. These entries show up in the Cloud Platform Console Logs page marked with flush, and include the start time of the request that generated the flush.

Communication between modules

Modules can share state by using the Datastore and Memcache. They can collaborate by assigning work between them using Task Queues. To access these shared services, use the corresponding App Engine APIs. Calls to these APIs are automatically mapped to the application’s namespace.

The Modules API provides functions to retrieve the address of a module, a version, or an instance. This allows an application to send requests from one module, version, or instance to another module, version, or instance. This works in both the development and production environments. The Modules API also provides functions that return information about the current operating environment (module, version, and instance).

The following code sample shows how to get the module name and instance id for a request:


ModulesService modulesApi = ModulesServiceFactory.getModulesService();

// Get the module name handling the current request.
String currentModuleName = modulesApi.getCurrentModule();
// Get the instance handling the current request.
int currentInstance = modulesApi.getCurrentInstance();

The instance ID of an automatic scaled module will be returned as a unique base64 encoded value, e.g. e4b565394caa.

You can communicate between modules in the same app by fetching the hostname of the target module:



// ...

ModulesService modulesApi = ModulesServiceFactory.getModulesService();

// ...
    try {
        URL url = new URL("http://" +
            modulesApi.getVersionHostname("my-backend-module","v1") +
        BufferedReader reader = new BufferedReader(
            new InputStreamReader(url.openStream()));
        String line;

        while ((line = reader.readLine()) != null) {
            // Do something...

    } catch (MalformedURLException e) {
        // ...
    } catch (IOException e) {
        // ...

You can also use the URL Fetch service.

To be safe, the receiving module should validate that the request is coming from a valid client. You can check that the Inbound-AppId header or user-agent-string matches the app-id fetched with the AppIdentity service. Or you can use OAuth to authenticate the request.

You can configure any manual or basic scaling module to accept requests from other modules in your app by restricting its handler to only allow administrator accounts, using a <security-constraint> with a <role-name>admin</role-name> in the module's web.xml deployment descriptor. With this restriction in place, any URLFetch from any other module in the app will be automatically authenticated by App Engine, and any request that is not from the application will be rejected.

If you want a module to receive requests from anywhere, you must code your own secure solution as you would for any App Engine application. This is usually done by implementing a custom API and authentication mechanism.


The maximum number of modules and versions that you can deploy depends on your app's pricing:

Limit Free App Paid App
Maximum Modules Per App 5 20
Maximum Versions Per App 15 60

There is also a limit to the number of instances for each module with basic or manual scaling:

Maximum Instances per Manual/Basic Scaling Version
Free App Paid App US Paid App EU
20 200 25