Considerations for Designing and Running an Application in the Cloud

Page last updated:

Application Design for the Cloud

Applications written in supported application frameworks often run unmodified on Cloud Foundry, if the application design follows a few simple guidelines. Following these guidelines makes an application cloud-friendly, and facilitates deployment to Cloud Foundry and other cloud platforms.

The following guidelines represent best practices for developing modern applications for cloud platforms. For more detailed reading about good app design for the cloud, see The Twelve-Factor App.

Avoid Writing to the Local File System

Applications running on Cloud Foundry should not write files to the local file system for the following reasons:

  • Local file system storage is short-lived. When an application instance crashes or stops, the resources assigned to that instance are reclaimed by the platform including any local disk changes made since the app started. When the instance is restarted, the application will start with a new disk image. Although your application can write local files while it is running, the files will disappear after the application restarts.

  • Instances of the same application do not share a local file system. Each application instance runs in its own isolated container. Thus a file written by one instance is not visible to other instances of the same application. If the files are temporary, this should not be a problem. However, if your application needs the data in the files to persist across application restarts, or the data needs to be shared across all running instances of the application, the local file system should not be used. We recommend using a shared data service like a database or blobstore for this purpose.

For example, instead of using the local file system, you can use a Cloud Foundry service such as the MongoDB document database or a relational database like MySQL or Postgres. Another option is to use cloud storage providers such as Amazon S3, Google Cloud Storage, Dropbox, or Box. If your application needs to communicate across different instances of itself, consider a cache like Redis or a messaging-based architecture with RabbitMQ.

Cookies Accessible across Applications

In an environment with shared domains, cookies might be accessible across applications.

Many tracking tools such as Google Analytics and Mixpanel use the highest available domain to set their cookies. For an application using a shared domain such as example.com, a cookie set to use the highest domain has a Domain attribute of .example.com in its HTTP response header. For example, an application at my-app.shared-domain.com might be able to access the cookies for an application at your-app.shared-domain.com.

Consider whether you want your applications or tools that use cookies to set and store the cookies at the highest available domain.

Sticky Sessions

Cloud Foundry supports session affinity or “sticky sessions” for incoming HTTP requests to compatible applications.

Sticky sessions means that when multiple instances of an application are running on Cloud Foundry, requests from a particular client always reach the same application instance. This allows applications to store session data specific to a user session.

Sticky sessions require applications to support returning a JSESSIONID cookie in responses.

If an application returns a JSESSIONID cookie to a client request, the Cloud Foundry routing tier appends a second cookie, called VCAP_ID. On subsequent requests, the client must provide both the JSESSIONID and VCAP_ID cookies. The Cloud Foundry routing tier uses the VCAP_ID to forward client requests to the same application instance every time.

If the application instance identified by the VCAP_ID crashes, the router attempts to route the request to a different instance of the application. If the router finds a healthy instance of the application, it initiates a new sticky session.

Note: Cloud Foundry does not persist or replicate HTTP session data across application instances. If an instance of an application crashes or is stopped, session data for that instance is lost. If you require session data to persist across crashed or stopped instances, or to be shared by all instances of an application, store session data in a Cloud Foundry marketplace service that offers data persistence.

HTTP Headers

HTTP traffic passed from the Cloud Foundry router to an app includes the the following HTTP headers:

  • X-Forwarded-Proto gives the scheme of the HTTP request from the client. The scheme is HTTP if the client made an insecure request or HTTPS if the client made a secure request. Developers can configure their apps to reject insecure requests by inspecting the HTTP headers of incoming traffic and rejecting traffic that includes X-Forwarded-Proto with the scheme of HTTP.

  • X-Forwarded-For gives the IP address of the client originating the request.

Port Limitations

Applications running on Cloud Foundry receive requests through the URLs configured for the application. HTTP requests arrive on ports 80 and 443. Additionally, Cloud Foundry requires a channel for TCP/WebSocket traffic. The default cf-release manifest assigns port 4443 for TCP/WebSocket communications.

If your load balancer requires that you use a different port for TCP/WebSocket traffic, you must do the following in order to access logs from your app with the cf logs APP_NAME command:

  • Set the value of the port sub-key of the logger_endpoint key in your manifest to the required value.
  • Configure your HAProxy or load balancer to receive TCP traffic on the port that you specified.

Cloud Foundry Updates and Your Application

For application management purposes, Cloud Foundry may need to stop and restart your application instances. If this occurs, Cloud Foundry performs the following steps:

  1. Cloud Foundry sends a single termination signal to the root process that your start command invokes.

  2. Cloud Foundry waits 10 seconds to allow your application to cleanly shut down any child processes and handle any open connections.

  3. After 10 seconds, Cloud Foundry forcibly shuts down your application.

Your application should accept and handle the termination signal to ensure that it shuts down gracefully.

Ignore Unnecessary Files When Pushing

By default, when you push an application, all files in the application’s project directory tree are uploaded to your Cloud Foundry instance, except version control or configuration files with the following file extensions:

  • .cfignore
  • _darcs
  • .DS_Store
  • .git
  • .gitignore
  • .hg
  • /manifest.yml
  • .svn

If the application directory contains other files (such as temp or log files), or complete subdirectories that are not required to build and run your application, the best practice is to exclude them using a .cfignore file. (.cfignore is similar to git’s .gitignore, which allows you to exclude files and directories from git tracking.) Especially with a large application, uploading unnecessary files slows down application deployment.

Specify the files or file types you wish to exclude from upload in a text file, named .cfignore, in the root of your application directory structure. For example, these lines exclude the “tmp” and “log” directories.

    tmp/
    log/

The file types you will want to exclude vary, based on the application frameworks you use. The .gitignore templates for common frameworks, available at https://github.com/github/gitignore, are a useful starting point.

Run Multiple Instances to Increase Availability

When a DEA is upgraded, the applications running on it are shut down gracefully, then restarted on another DEA. To avoid the risk of an application being unavailable during a Cloud Foundry upgrade processes, you should run more than one instance of the application.

Using Buildpacks

A buildpack consists of bundles of detection and configuration scripts that provide framework and runtime support for your applications. When you deploy an application that needs a buildpack, Cloud Foundry installs the buildpack on the Droplet Execution Agent (DEA) where the application runs.

For more information, see the Buildpacks topic.