Skip Navigation
Show nav
Heroku Dev Center
  • Get Started
  • Documentation
  • Changelog
  • Search
  • Get Started
    • Node.js
    • Ruby on Rails
    • Ruby
    • Python
    • Java
    • PHP
    • Go
    • Scala
    • Clojure
  • Documentation
  • Changelog
  • More
    Additional Resources
    • Home
    • Elements
    • Products
    • Pricing
    • Careers
    • Help
    • Status
    • Events
    • Podcasts
    • Compliance Center
    Heroku Blog

    Heroku Blog

    Find out what's new with Heroku on our blog.

    Visit Blog
  • Log inorSign up

Getting Started on Heroku with Scala and Play

Introduction

This tutorial will have you deploying a Scala app in minutes. The app in this example is built using the Play framework.

Hang on for a few more minutes to learn how it all works, so you can make the most out of Heroku.

The tutorial assumes that you have:

  • A verified Heroku Account
  • sbt or activator installed.
  • An Eco dynos plan subscription (recommended)

As of November 28th, 2022, free Heroku dynos, free Heroku Postgres and free Heroku Data for Redis plans are no longer available.

We recommend using our low-cost plans to complete this tutorial. Eligible students can apply for platform credits through our new Heroku for GitHub Students program.

Set up

The Heroku CLI requires Git, the popular version control system. If you don’t already have Git installed, complete the following before proceeding:

  • Git installation
  • First-time Git setup

In this step you’ll install the Heroku Command Line Interface (CLI). You use the CLI to manage and scale your applications, provision add-ons, view your application logs, and run your application locally.

Download and run the installer for your platform:

apple logomacOS

$ brew tap heroku/brew && brew install heroku

windows logoWindows

Download the appropriate installer for your Windows installation:

64-bit installer

32-bit installer

Once installed, you can use the heroku command from your command shell.

On Windows, start the Command Prompt (cmd.exe) or Powershell to access the command shell.

Use the heroku login command to log in to the Heroku CLI:

$ heroku login
heroku: Press any key to open up the browser to login or q to exit
 ›   Warning: If browser does not open, visit
 ›   https://cli-auth.heroku.com/auth/browser/***
heroku: Waiting for login...
Logging in... done
Logged in as me@example.com

This command opens your web browser to the Heroku login page. If your browser is already logged in to Heroku, simply click the Log in button displayed on the page.

This authentication is required for both the heroku and git commands to work correctly.

If you’re behind a firewall that requires use of a proxy to connect with external HTTP/HTTPS services, you can set the HTTP_PROXY or HTTPS_PROXY environment variables in your local development environment before running the heroku command.

Prepare the app

In this step, you will prepare a sample application that’s ready to be deployed to Heroku.

If you are new to Heroku, it is recommended that you complete this tutorial using the Heroku-provided sample application.

However, if you have your own existing application that you want to deploy instead, see this article to learn how to prepare it for Heroku deployment.

To clone the sample application so that you have a local version of the code that you can then deploy to Heroku, execute the following commands in your local command shell or terminal:

$ git clone https://github.com/heroku/scala-getting-started.git
$ cd scala-getting-started

You now have a functioning git repository that contains a simple application as well as a build.sbt file, which is used by Scala’s dependency manager, sbt.

Deploy the app

In this step you will deploy the app to Heroku.

Using a dyno and a database to complete this tutorial counts towards your usage. Delete your app, and database as soon as you’re done to control costs.

 

The scala buildpack auto-provisions a Mini Heroku Postgres database for your app. By default, apps use Eco dynos if you are subscribed to Eco. Otherwise, it defaults to Basic dynos. The Eco dynos plan is shared across all Eco dynos in your account and is recommended if you plan on deploying many small apps to Heroku. Learn more here. Eligible students can apply for platform credits through our Heroku for GitHub Students program.

Create an app on Heroku, which prepares Heroku to receive your source code:

$ heroku create
Creating nameless-lake-8055 in organization heroku... done, stack is heroku-20
http://nameless-lake-8055.herokuapp.com/ | https://git.heroku.com/nameless-lake-8055.git
Git remote heroku added

When you create an app, a git remote (called heroku) is also created and associated with your local git repository.

Heroku generates a random name (in this case nameless-lake-8055) for your app, or you can pass a parameter to specify your own app name.

Now deploy your code:

$ git push heroku main
Counting objects: 29, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (24/24), done.
Writing objects: 100% (29/29), 5.89 KiB | 0 bytes/s, done.
Total 29 (delta 0), reused 0 (delta 0)
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Play 2.x - Scala app detected
remote: -----> Installing OpenJDK 1.8... done
remote: -----> Priming Ivy cache (Scala-2.11, Play-2.3)... done
remote: -----> Running: sbt compile stage
remote:        Downloading sbt launcher for 0.13.8:
remote:          From  http://typesafe.artifactoryonline.com/typesafe/ivy-releases/org.scala-sbt/sbt-launch/0.13.8/sbt-launch.jar
remote:            To  /tmp/scala_buildpack_build_dir/.sbt_home/launchers/0.13.8/sbt-launch.jar
remote:        OpenJDK 64-Bit Server VM warning: ignoring option MaxPermSize=384m; support was removed in 8.0
remote:        Getting org.scala-sbt sbt 0.13.8 ...
remote:        downloading https://repo.typesafe.com/typesafe/ivy-releases/org.scala-sbt/sbt/0.13.8/jars/sbt.jar ...
remote:         [SUCCESSFUL ] org.scala-sbt#sbt;0.13.8!sbt.jar (85ms)
...
remote:        [info] Done packaging.
remote:        [success] Total time: 20 s, completed Apr 15, 2015 7:42:31 PM
remote: -----> Dropping ivy cache from the slug
remote: -----> Dropping sbt boot dir from the slug
remote: -----> Dropping compilation artifacts from the slug
remote: -----> Discovering process types
remote:        Procfile declares types            -> (none)
remote:        Default types for Play 2.x - Scala -> web

Now visit the app at the URL generated by its app name. As a handy shortcut, you can open the website as follows:

$ heroku open

View logs

Heroku treats logs as streams of time-ordered events aggregated from the output streams of all your app and Heroku components, providing a single channel for all of the events.

View information about your running app using one of the logging commands, heroku logs --tail:

$ heroku logs --tail
2015-04-15T19:43:23.035646+00:00 app[web.1]: Picked up JAVA_TOOL_OPTIONS: -Xmx384m -Xss512k -Dfile.encoding=UTF-8 -Djava.rmi.server.useCodebaseOnly=true
2015-04-15T19:43:23.453052+00:00 app[web.1]: Play server process ID is 3
2015-04-15T19:43:25.088586+00:00 app[web.1]: [info] application - Application has started
2015-04-15T19:43:25.113442+00:00 app[web.1]: [info] play - Application started (Prod)
2015-04-15T19:43:25.532132+00:00 app[web.1]: [info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:41695
2015-04-15T19:43:25.957858+00:00 heroku[web.1]: State changed from starting to up
2015-04-15T19:48:46.841884+00:00 heroku[router]: at=info method=GET path="/" host=nameless-lake-8055.herokuapp.com request_id=b183fc3f-503c-4943-90a2-eb1f1e7bce39 fwd="68.32.164.116" dyno=web.1 connect=1ms service=490ms status=200 bytes=559

Visit your application in the browser again, and you’ll see another log message generated.

Press Control+C to stop streaming the logs.

Define a Procfile

Use a Procfile, a text file in the root directory of your application, to explicitly declare what command should be executed to start your app.

The Procfile in the example app you deployed looks like this:

web: target/universal/stage/bin/play-getting-started -Dhttp.port=${PORT}

This declares a single process type, web, and the command needed to run it. The name web is important here. It declares that this process type will be attached to the HTTP routing stack of Heroku, and receive web traffic when deployed.

The syntax of the Procfile is important - Heroku runs the exact command specified here when it starts a web dyno - and it runs it in a Unix environment.

When running locally under Windows, you may receive an error because the Unix way of passing in environment variables ($PORT) and of concatenating paths (:) is incompatible.

The example also contains a Procfile.windows, which looks like this: web: target/universal/stage/bin/play-getting-started -Dhttp.port=%PORT%

When you see instructions to run your app with heroku local, append an extra -f Procfile.windows flag to ensure your Windows-specific Procfile is picked up. For example: heroku local web -f Procfile.windows

Procfiles can contain additional process types. For example, you might declare one for a background worker process that processes items off of a queue.

Scale the app

Right now, your app is running on a single web dyno. Think of a dyno as a lightweight container that runs the command specified in the Procfile.

You can check how many dynos are running using the ps command:

$ heroku ps
=== web (Eco): `target/universal/stage/bin/play-getting-started -Dhttp.port=$PORT`
web.1: up 2014/08/14 11:10:07 (~ 3m ago)

By default, your app is deployed on an eco dyno. Eco dynos will sleep after a half hour of inactivity (if they don’t receive any traffic). This causes a delay of a few seconds for the first request upon waking. Subsequent requests will perform normally. Eco dynos also consume from a monthly, account-level quota of eco dyno hours - as long as the quota is not exhausted, all eco apps can continue to run.

To avoid dyno sleeping, you can upgrade to a Basic or Professional dyno type as described in the Dyno Types article. For example, if you migrate your app to a professional dyno, you can easily scale it by running a command telling Heroku to execute a specific number of dynos, each running your web process type.

Scaling an application on Heroku is equivalent to changing the number of dynos that are running. Scale the number of web dynos to zero:

$ heroku ps:scale web=0

Access the app again by hitting refresh on the web tab, or heroku open to open it in a web tab. You will get an error message because you no longer have any web dynos available to serve requests.

Scale it up again:

$ heroku ps:scale web=1

Declare app dependencies

Heroku recognizes an app as Scala by the existence of a build.sbt file in the root directory.

The demo app you deployed already has a build.sbt (see it here). Here’s an excerpt:

name := """play-getting-started"""

version := "1.0-SNAPSHOT"

lazy val root = (project in file(".")).enablePlugins(PlayScala)

scalaVersion := "2.11.1"

libraryDependencies ++= Seq(
  jdbc,
  cache,
  ws
)

The build.sbt file specifies dependencies that should be installed with your application. When an app is deployed, Heroku reads this file and installs the dependencies using the sbt compile stage command.

Another file, system.properties, determines the version of Java to use. The contents of this file, which is optional, is quite straightforward:

java.runtime.version=1.8

Run sbt compile stage in your local directory to install the dependencies, preparing your system for running the app locally:

$ sbt compile stage
[info] Loading project definition from /private/tmp/play-getting-started/project
[info] Updating {file:/private/tmp/play-getting-started/project/}play-getting-started-build...
[info] Resolving org.fusesource.jansi#jansi;1.4 ...
[info] Done updating.
[info] Set current project to play-getting-started (in build file:/private/tmp/play-getting-started/)
[info] Updating {file:/private/tmp/play-getting-started/}root...
[info] Resolving jline#jline;2.11 ...
...
[info] Done packaging.
[info] Packaging /private/tmp/play-getting-started/target/play-getting-started-1.0-SNAPSHOT-assets.jar ...
[info] Done packaging.
model contains 19 documentable templates
[info] Main Scala API documentation successful.
[info] Packaging /private/tmp/play-getting-started/target/scala-2.11/play-getting-started_2.11-1.0-SNAPSHOT-javadoc.jar ...
[info] Done packaging.
[success] Total time: 7 s, completed Apr 15, 2015 2:53:03 PM

Once dependencies are installed, you will be ready to run your app locally.

Run the app locally

Now start your application locally using the heroku local command, which was installed as part of the Heroku CLI:

$ heroku local web -f Procfile.windows
14:56:42 web.1  | started with pid 31232
14:56:43 web.1  | Play server process ID is 31232
14:56:43 web.1  | [info] play - Application started (Prod)
14:56:43 web.1  | [info] play - Listening for HTTP on /0:0:0:0:0:0:0:0:90005000

Just like Heroku, heroku local examines the Procfile to determine what to run.

Open http://localhost:5000http://localhost:9000 with your web browser. You should see your app running locally.

To stop the app from running locally, go back to your terminal window and press Ctrl+C to exit.

Push local changes

In this step you’ll learn how to propagate a local change to the application through to Heroku. As an example, you’ll modify the application to add an additional dependency and the code to use it.

Modify build.sbt to include a dependency for jscience. The libraryDependencies section should look something like this:

libraryDependencies ++= Seq(
  jdbc,
  cache,
  ws,
  "org.jscience" % "jscience" % "4.3.1"
)

Modify app/controllers/Application.scala so that it imports this library at the start:

import javax.measure.unit.SI.KILOGRAM
import javax.measure.quantity.Mass
import org.jscience.physics.model.RelativisticModel
import org.jscience.physics.amount.Amount

Add a new route action to use the code. Something like this:

object Application extends Controller {

  def index = Action {
    RelativisticModel.select()
    val m = Amount.valueOf("12 GeV").to(KILOGRAM)
    val testRelativity = s"E=mc^2: 12 GeV = $m"
    Ok(views.html.index(testRelativity))
  }

  ...

}

Now test locally:

$ sbt compile stage
$ heroku local web

Visiting your application at http://localhost:5000http://localhost:9000, you should see some great scientific conversions displayed:

E=mc^2: 12 GeV = (2.139194076302506E-26 ± 1.4E-42) kg

Now deploy. Almost every deploy to Heroku follows this same pattern. First, add the modified files to the local git repository:

$ git add .

Now commit the changes to the repository:

$ git commit -m "Demo"

Now deploy, just as you did previously:

$ git push heroku main

Finally, check that everything is working:

$ heroku open

Provision add-ons

Add-ons are third-party cloud services that provide out-of-the-box additional services for your application, from persistence through logging to monitoring and more.

By default, Heroku stores 1500 lines of logs from your application. However, it makes the full log stream available as a service - and several add-on providers have written logging services that provide things such as log persistence, search, and email and SMS alerts.

In this step you will provision one of these logging add-ons, Papertrail.

Provision the papertrail logging add-on:

$ heroku addons:create papertrail
Adding papertrail on warm-eyrie-9006... done, v8 (free)
Welcome to Papertrail. Questions and ideas are welcome (support@papertrailapp.com). Happy logging!
Use `heroku addons:docs papertrail` to view documentation.

The add-on is now deployed and configured for your application. You can list add-ons for your app like so:

$ heroku addons

To see this particular add-on in action, visit your application’s Heroku URL a few times. Each visit will generate more log messages, which should now get routed to the papertrail add-on. Visit the papertrail console to see the log messages:

$ heroku addons:open papertrail

Your browser will open up a Papertrail web console, showing the latest log events. The interface lets you search and set up alerts:

Image

It may take a few minutes for this particular add-on to start piping the log events after an initial setup.

Start a one-off dyno

You can run a command, typically scripts and applications that are part of your app, in a one-off dyno using the heroku run command. It can also be used to launch a console process attached to your local terminal for experimenting in your app’s environment, or code that you deployed with your application:

$ heroku run console
Running `console` attached to terminal... up, run.9125
Picked up JAVA_TOOL_OPTIONS: -Xmx384m -Xss512k -Dfile.encoding=UTF-8 -Djava.rmi.server.useCodebaseOnly=true
Failed to created JLineReader: java.lang.NoClassDefFoundError: jline/console/completer/Completer
Falling back to SimpleReader.
Welcome to Scala
Type in expressions to have them evaluated.
Type :help for more information.

scala> import javax.measure.unit.SI.KILOGRAM
scala> import javax.measure.quantity.Mass
scala> import org.jscience.physics.model.RelativisticModel
scala> import org.jscience.physics.amount.Amount
scala> RelativisticModel.select()
scala> Amount.valueOf("2 GeV").to(KILOGRAM)
res4: org.jscience.physics.amount.Amount[javax.measure.quantity.Mass] = (3.5653234605041767E-27 ? 3.6E-43) kg

Don’t forget to type Ctrl-C to exit the shell and terminate the dyno.

If you receive an error, Error connecting to process, then you may need to configure your firewall.

Define config vars

Heroku lets you externalise configuration - storing data such as encryption keys or external resource addresses in config vars.

At runtime, config vars are exposed as environment variables to the application. For example, modify app/controllers/Application.scala so that the method grabs an energy value from the ENERGY environment variable:

object Application extends Controller {
  def index = Action {
    RelativisticModel.select()
    val energy = scala.util.Properties.envOrElse("ENERGY", "12 GeV")
    val m = Amount.valueOf(energy).to(KILOGRAM)
    val testRelativity = s"E=mc^2: $energy = $m"
    Ok(views.html.index(testRelativity))
  }
}

Now compile the app again so that this change is integrated by running sbt compile stage.

heroku local will automatically set up the environment based on the contents of the .env file in your local directory. In the top-level directory of your project there is already a .env file that has the following contents:

ENERGY=20 GeV

If you run the app with heroku local and visit it at http://localhost:5000http://localhost:9000, you’ll see the conversion value for 20 GeV.

To set the config var on Heroku, execute the following:

$ heroku config:set ENERGY="20 GeV"
Setting config vars and restarting warm-eyrie-9006... done, v10
ENERGY: 20 GeV

View the config vars that are set using heroku config:

$ heroku config
== nameless-lake-8055 Config Vars
PAPERTRAIL_API_TOKEN: erdKhPeeeehIcdfY7ne
ENERGY: 20 GeV
...

Deploy your changed application to Heroku to see this in action.

Use a database

The add-on marketplace has a large number of data stores, from Redis and MongoDB providers, to Postgres and MySQL. In this step you will learn about the Heroku Mini Postgres add-on that is provisioned automatically on all Scala app deploys.

A database is an add-on, and so you can find out a little more about the database provisioned for your app using the addons command in the CLI:

$ heroku addons
=== nameless-lake-8055 Configured Add-ons
heroku-postgresql:mini  HEROKU_POSTGRESQL_BLUE
papertrail:choklad
...

Listing the config vars for your app will display the URL that your app is using to connect to the database, DATABASE_URL:

$ heroku config
=== nameless-lake-8055 Config Vars
DATABASE_URL:               postgres://qplhasewkhqyxp:YXDPSRus9MrU4HglCPzjhOevee@ec2-54-204-47-58.compute-1.amazonaws.com:5432/dc9qsdnghia6v1
...

Heroku also provides a pg command that shows a lot more:

$ heroku pg
== HEROKU_POSTGRESQL_BLUE_URL (DATABASE_URL)
Plan:        Mini
Status:      Available
Connections: 0
PG Version:  9.4.1
Created:     2014-08-08 13:54 UTC
Data Size:   6.5 MB
Tables:      0
Rows:        1/10000 (In compliance)
Fork/Follow: Unsupported
Rollback:    Unsupported

This indicates I have a mini database, running Postgres 9.4, with a single row of data.

The example app you deployed already has database functionality. Uncomment the following lines in the application’s conf/application.conf file to enable it.

db.default.driver=org.postgresql.Driver
db.default.url=${DATABASE_URL}

The db.default.url property retrieves the environment variable DATABASE_URL that is set by the database add-on, and Play uses it to establish a connection.

The code that accesses the database can be found in app/controllers/Application.scala. The db action inserts values into a table called tick.

def db = Action {
    var out = ""
    val conn = DB.getConnection()
    try {
        val stmt = conn.createStatement
        stmt.executeUpdate("CREATE TABLE IF NOT EXISTS ticks (tick timestamp)")
        stmt.executeUpdate("INSERT INTO ticks VALUES (now())")

        val rs = stmt.executeQuery("SELECT tick FROM ticks")

        while (rs.next) {
            out += "Read from DB: " + rs.getTimestamp("tick") + "\n"
        }
    } finally {
        conn.close()
    }
    Ok(out)
}

This ensures that when you access your app using the /db route, a new row will be added to the tick table, and all the rows will then be returned so that they can be rendered in the output.

Now commit your changes and redeploy by running the following commands.

$ git add conf/application.conf
$ git commit -m "Added db"
$ git push heroku main

When you access your app’s /db route, you will see something like this:

Read from DB: 2014-08-08 14:48:25.155241
Read from DB: 2014-08-08 14:51:32.287816
Read from DB: 2014-08-08 14:51:52.667683

Assuming that you have Postgres installed locally, use the heroku pg:psql command to connect to the remote database and see all the rows:

$ heroku pg:psql
heroku pg:psql
psql (9.3.2, server 9.3.3)
SSL connection (cipher: DHE-RSA-AES256-SHA, bits: 256)
Type "help" for help.
=> SELECT * FROM ticks;
            tick
----------------------------
 2014-08-08 14:48:25.155241
 2014-08-08 14:51:32.287816
 2014-08-08 14:51:52.667683
 2014-08-08 14:51:53.1871
 2014-08-08 14:51:54.75061
 2014-08-08 14:51:55.161848
 2014-08-08 14:51:56.197663
 2014-08-08 14:51:56.851729
(8 rows)
=> \q

Read more about Heroku Postgres.

A similar technique can be used to install MongoDB or Redis add-ons.

Next steps

You now know how to deploy an app, change its configuration, view logs, scale, and attach add-ons.

Here’s some recommended reading. The first, an article, will give you a firmer understanding of the basics. The second is a pointer to the main Scala category here on Dev Center:

  • Read How Heroku Works for a technical overview of the concepts you’ll encounter while writing, configuring, deploying and running applications.
  • Read Deploying Scala Apps on Heroku to understand how to take an existing Scala app and deploy it to Heroku.
  • Read Heroku Play Framework Support to understand more about Heroku’s support for Play.
  • Visit the Play and Scala category to learn more about developing and deploying Play and Scala applications.
  • Learn more about the Heroku developer experience and CI/CD features in the Heroku Enterprise Developer Learning Journey.

Information & Support

  • Getting Started
  • Documentation
  • Changelog
  • Compliance Center
  • Training & Education
  • Blog
  • Podcasts
  • Support Channels
  • Status

Language Reference

  • Node.js
  • Ruby
  • Java
  • PHP
  • Python
  • Go
  • Scala
  • Clojure

Other Resources

  • Careers
  • Elements
  • Products
  • Pricing

Subscribe to our monthly newsletter

Your email address:

  • RSS
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku Blog
    • Heroku News Blog
    • Heroku Engineering Blog
  • Heroku Podcasts
  • Twitter
    • Dev Center Articles
    • Dev Center Changelog
    • Heroku
    • Heroku Status
  • Facebook
  • Instagram
  • Github
  • LinkedIn
  • YouTube
Heroku is acompany

 © Salesforce.com

  • heroku.com
  • Terms of Service
  • Privacy
  • Cookies
  • Cookie Preferences