<!-- mobian-agent-page publisher="dailydev" canonical="https://daily.dev/blog/build-rest-api-with-scala-play-framework" -->

---
title: Build REST API with Scala Play Framework | daily.dev
description: Learn how to build a robust REST API using Scala and Play Framework, covering setup, security, performance, and deployment strategies.
canonical: https://daily.dev/blog/build-rest-api-with-scala-play-framework/
og:type: article
og:url: https://daily.dev/blog/build-rest-api-with-scala-play-framework/
og:title: Build REST API with Scala Play Framework | daily.dev
og:description: Learn how to build a robust REST API using Scala and Play Framework, covering setup, security, performance, and deployment strategies.
og:image: https://media.daily.dev/image/upload/s--l6RvOb41--/f_auto,q_auto/v1/recruiter-landing/66d8f632626438aa32fb868a_224aa26f9f3eb6538ad7962c9c952d0b_06fe962871?_a=BAMAMiB80
og:site_name: daily.dev
og:locale: en_US
article:published_time: 2024-09-05
article:modified_time: 2026-05-25T06:17:33.264Z
article:author: Alex Carter
twitter:card: summary_large_image
twitter:site: @dailydotdev
twitter:creator: @dailydotdev
twitter:title: Build REST API with Scala Play Framework | daily.dev
twitter:description: Learn how to build a robust REST API using Scala and Play Framework, covering setup, security, performance, and deployment strategies.
twitter:image: https://media.daily.dev/image/upload/s--l6RvOb41--/f_auto,q_auto/v1/recruiter-landing/66d8f632626438aa32fb868a_224aa26f9f3eb6538ad7962c9c952d0b_06fe962871?_a=BAMAMiB80
---

Want to create a powerful REST API using [Scala](https://www.scala-lang.org/) and [Play Framework](https://www.playframework.com/)? Here's a quick guide:

1.  Set up your project using [SBT](https://www.scala-sbt.org/) and Play Framework templates
2.  Design your API endpoints and data models
3.  Implement controllers to handle HTTP requests
4.  Add database integration for data persistence
5.  Secure your API with authentication and authorization
6.  Test thoroughly using unit and integration tests
7.  Optimize performance with caching and async programming
8.  Deploy to production using [Heroku](https://www.heroku.com/), [Docker](https://www.docker.com/), or manual server setup

Key benefits of using Scala Play for REST APIs:

-   Concise, expressive Scala syntax
-   Built-in JSON parsing and validation
-   Non-blocking, reactive architecture
-   Robust testing tools

Let's break down the essential steps to build your API:

| Step | Description |
| --- | --- |
| Project Setup | Use SBT to create a new Play project |
| API Design | Plan your endpoints, models, and HTTP methods |
| Controllers | Implement request handling logic |
| Database | Integrate with [MySQL](https://www.mysql.com/), [PostgreSQL](https://www.postgresql.org/) etc. |
| Security | Add authentication with JWT tokens |
| Testing | Write unit and integration tests |
| Performance | Use caching and async programming |
| Deployment | Package and deploy to production |

Ready to start coding? Let's dive in and build your Scala Play REST API!

## Related video from YouTube

::: @iframe https://www.youtube-nocookie.com/embed/2y49wFiXhQI

## What You Need to Start

Before diving into building a REST API with [Scala Play Framework](https://daily.dev/blog/scala-for-beginners-an-introduction), let's cover the essential skills and tools you'll need.

### Required Skills

To follow this guide effectively, you should have:

-   Basic knowledge of Scala programming
-   Understanding of REST principles
-   Familiarity with web development concepts

While not mandatory, experience with Java can be helpful, as Scala runs on the Java Virtual Machine (JVM).

### Required Software

To set up your development environment, install the following:

1.  **Java Development Kit (JDK)**: Install JDK 17 or higher. You can check your Java version by running:
    
    ```
    java -version
    ```
    
2.  **sbt (Scala Build Tool)**: This is crucial for managing Scala projects. Install the latest version.
    
3.  **[Scala IDE](https://app.daily.dev/tags/scala)**: While not strictly necessary, an IDE can significantly improve your development experience. [IntelliJ IDEA](https://www.jetbrains.com/idea/) is a popular choice with good Play Framework integration.
    

Here's a quick setup guide:

| Step | Action | Command/Note |
| --- | --- | --- |
| 1   | Install JDK | Download from Adoptium |
| 2   | Install sbt | Follow instructions on sbt website |
| 3   | Create new project | `sbt new playframework/play-scala-seed.g8` |
| 4   | Run the project | `cd project-directory && sbt run` |

Once you have these tools installed, you're ready to start building your REST API with Scala Play Framework.

## Starting Your Project

Now that you have the necessary tools installed, let's dive into creating your first Play Framework project for building a REST API with Scala.

### Making a New Project

To create a new Play Framework project, open your terminal and run:

```
sbt new playframework/play-scala-seed.g8
```

You'll be prompted to name your project and provide an organization name. For example:

```
name [play-scala-seed]: rest-api-demo
organization [com.example]: com.mycompany
```

After the project is generated, navigate to the project directory:

```
cd rest-api-demo
```

To start the application, run:

```
sbt run
```

The first time you run this command, it may take a few minutes to download and compile dependencies. Once complete, you can access the default welcome page at `http://localhost:9000`.

### How Files are Organized

Play Framework follows a standard project layout to keep your code organized. Here's a breakdown of the key directories:

| Directory | Purpose |
| --- | --- |
| `app/` | Contains core Scala files (controllers, models, etc.) |
| `conf/` | Holds configuration files and route definitions |
| `public/` | Stores static assets (JavaScript, CSS, images) |
| `test/` | Contains test files |

The `app/` directory is where you'll spend most of your time developing your REST API. It's further divided into subdirectories:

-   `controllers/`: Houses your API endpoint logic
-   `models/`: Stores your data models
-   `views/`: Contains HTML templates (less used in REST APIs)

### Adding Needed Libraries

To add libraries for your REST API, you'll need to modify the `build.sbt` file in your project's root directory. Here's how to add dependencies:

```scala
libraryDependencies ++= Seq(
  "org.playframework" %% "play-slick" % "5.0.0",
  "org.postgresql" % "postgresql" % "42.3.1"
)
```

This example adds Play [Slick](https://scala-slick.org/) for database access and PostgreSQL driver. After modifying `build.sbt`, reload your sbt shell or restart your application to download the new dependencies.

## Planning Your API

When building a REST API with Scala Play Framework, careful planning is key to creating a well-structured and efficient system. Let's break down the essential steps:

### Choosing API Endpoints

Start by identifying the resources your API will manage. For our example, we'll create a todo list application. Here are the endpoints we'll need:

| Endpoint | HTTP Method | Description |
| --- | --- | --- |
| /api/todos | GET | Retrieve all todo items |
| /api/todos/{id} | GET | Get a specific todo item |
| /api/todos | POST | Create a new todo item |
| /api/todos/{id} | PUT | Update an existing todo item |
| /api/todos/{id} | DELETE | Delete a todo item |

These endpoints follow REST conventions, using nouns to represent resources and HTTP methods to define actions.

### Creating Data Models

For our todo list app, we'll use a simple data model. In Scala, we can define it as a case class:

```scala
case class Todo(id: Long, description: String, isComplete: Boolean)
```

This model represents each todo item with an ID, description, and completion status.

### Picking HTTP Methods

Choose HTTP methods based on the actions you want to perform:

-   **GET**: Use for retrieving data without modifying the server state.
-   **POST**: Use for creating new resources.
-   **PUT**: Use for updating existing resources.
-   **DELETE**: Use for removing resources.

For example, to create a new todo item, you'd use:

```
POST /api/todos
```

With a request body containing the todo item details.

## Building Models and DTOs

In Scala Play Framework, we use case classes to define our data models and Data Transfer Objects (DTOs). This approach allows for easy serialization and deserialization of data, which is crucial for REST APIs.

### Making Case Classes

Let's create a case class for our todo list application:

```scala
case class Todo(id: Long, description: String, isComplete: Boolean)
```

This `Todo` class represents each item in our list with an ID, description, and completion status.

For API operations that don't require all fields, we can create a separate DTO:

```scala
case class NewTodo(description: String)
```

This `NewTodo` class is useful when creating a new todo item, where the ID is not yet assigned and the completion status is assumed to be false.

### Working with JSON

Play Framework provides tools to convert our case classes to and from JSON. Here's how to set up JSON formatters:

```scala
import play.api.libs.json._

object Todo {
  implicit val todoFormat: Format[Todo] = Json.format[Todo]
  implicit val newTodoFormat: Format[NewTodo] = Json.format[NewTodo]
}
```

These implicit formatters allow automatic JSON conversion in our controllers.

To use these formatters:

```scala
def createTodo() = Action(parse.json) { request =>
  request.body.validate[NewTodo].map { newTodo =>
    // Create a new Todo item
    val todo = Todo(id = generateId(), description = newTodo.description, isComplete = false)
    Ok(Json.toJson(todo))
  }.recoverTotal { errors =>
    BadRequest(Json.obj("message" -> JsError.toJson(errors)))
  }
}
```

This code snippet shows how to:

1.  Parse the incoming JSON request
2.  Validate it against our `NewTodo` model
3.  Create a new `Todo` item
4.  Return the created item as JSON

## Creating Controllers

Controllers in Play Framework handle API requests and business logic. They act as a bridge between incoming requests and your application's core functionality.

### Setting Up Controllers

To create a controller:

1.  Make a new file in the `app/controllers` directory
2.  Define a class that extends `AbstractController`
3.  Use [dependency injection](https://app.daily.dev/tags/dependency-injection) with the `@Inject` annotation

Here's a basic controller setup:

```scala
package controllers

import javax.inject._
import play.api.mvc._

@Singleton
class TodoController @Inject()(cc: ControllerComponents) extends AbstractController(cc) {
  // Controller methods go here
}
```

### Adding CRUD Operations

Implement methods for Create, Read, Update, and Delete operations:

```scala
def getAll(): Action[AnyContent] = Action.async { implicit request =>
  todoService.listAllItems.map { items =>
    Ok(Json.toJson(items))
  }
}

def add(): Action[AnyContent] = Action.async { implicit request =>
  TodoForm.form.bindFromRequest.fold(
    errorForm => {
      Future.successful(BadRequest("Error in form submission"))
    },
    data => {
      val newTodo = Todo(0, data.name, false)
      todoService.addItem(newTodo).map(_ => Created)
    }
  )
}

def update(id: Long): Action[AnyContent] = Action.async { implicit request =>
  // Update logic here
}

def delete(id: Long): Action[AnyContent] = Action.async { implicit request =>
  // Delete logic here
}
```

### Processing Requests

To handle incoming data:

1.  Use `request.body` to access the request payload
2.  Parse JSON data with Play's JSON library
3.  Validate input using Play's form binding

Example of processing a JSON request:

```scala
def createTodo(): Action[JsValue] = Action(parse.json) { request =>
  request.body.validate[Todo].fold(
    errors => {
      BadRequest(Json.obj("message" -> JsError.toJson(errors)))
    },
    todo => {
      // Process the valid todo item
      Created(Json.obj("message" -> "Todo created", "id" -> todo.id))
    }
  )
}
```

Remember to add your controller methods to the `conf/routes` file:

```
GET     /todos              controllers.TodoController.getAll()
POST    /todos              controllers.TodoController.add()
PUT     /todos/:id          controllers.TodoController.update(id: Long)
DELETE  /todos/:id          controllers.TodoController.delete(id: Long)
```

## Setting Up Routes

In Play Framework, routes connect incoming HTTP requests to the right controller actions. This crucial step ensures your API functions as intended.

### Creating Routes

To set up routes in Play Framework:

1.  Open the `conf/routes` file in your project.
2.  Define each route using this format:

```
HTTP_METHOD    /path    controller.ControllerName.actionMethod
```

For example:

```
GET     /todos              controllers.TodoController.getAll()
POST    /todos              controllers.TodoController.add()
PUT     /todos/:id          controllers.TodoController.update(id: Long)
DELETE  /todos/:id          controllers.TodoController.delete(id: Long)
```

### Linking URLs to Actions

When linking URLs to controller actions:

-   Use `:paramName` for single URL segments
-   Use `*paramName` to capture multiple segments

For instance:

```
GET     /files/*name        controllers.FileController.download(name: String)
```

This route captures all segments after `/files/` into the `name` parameter.

**Tip**: Add comments in your routes file for clarity:

```
# Get all todos
GET     /todos              controllers.TodoController.getAll()
```

###### sbb-itb-bfaad5b

## Adding a Database

To store and retrieve data for your REST API built with Scala Play Framework, you'll need to connect a database. Let's explore how to do this effectively.

### Picking a Database

When choosing a database for your Play Framework project, consider these options:

| Database Type | Examples | Best For |
| --- | --- | --- |
| Relational | MySQL, PostgreSQL | Structured data, complex queries |
| NoSQL | [MongoDB](https://www.mongodb.com/) | Flexible schemas, scalability |
| In-memory | [H2](https://www.h2database.com/) | Development, testing |

For this guide, we'll use MySQL as our database.

### Setting Up the Database

To set up MySQL with Play Framework:

1.  Add the following dependencies to your `build.sbt`:

```scala
libraryDependencies ++= Seq(
  jdbc,
  "mysql" % "mysql-connector-java" % "8.0.33"
)
```

2.  Configure the database connection in `conf/application.conf`:

```hocon
db.default.driver=com.mysql.jdbc.Driver
db.default.url="jdbc:mysql://localhost/playdb"
db.default.username=playdbuser
db.default.password="your_strong_password"
```

3.  Enable the Play JDBC plugin by adding this line to `conf/application.conf`:

```hocon
play.modules.enabled += "play.api.db.DBModule"
```

### Creating Database Access Code

To interact with your database, you'll need to create data access objects (DAOs) or repositories. Here's an example using Slick, a functional-relational mapper for Scala:

1.  Add Slick dependencies to `build.sbt`:

```scala
libraryDependencies ++= Seq(
  "com.typesafe.play" %% "play-slick" % "5.0.0",
  "com.typesafe.play" %% "play-slick-evolutions" % "5.0.0"
)
```

2.  Create a `User` model:

```scala
case class User(id: Long, name: String, email: String)
```

3.  Define a `UserRepository`:

```scala
import javax.inject.{Inject, Singleton}
import play.api.db.slick.DatabaseConfigProvider
import slick.jdbc.JdbcProfile

import scala.concurrent.{ExecutionContext, Future}

@Singleton
class UserRepository @Inject()(dbConfigProvider: DatabaseConfigProvider)(implicit ec: ExecutionContext) {
  private val dbConfig = dbConfigProvider.get[JdbcProfile]

  import dbConfig._
  import profile.api._

  private class UserTable(tag: Tag) extends Table[User](tag, "users") {
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def name = column[String]("name")
    def email = column[String]("email")
    def * = (id, name, email) <> ((User.apply _).tupled, User.unapply)
  }

  private val users = TableQuery[UserTable]

  def create(name: String, email: String): Future[User] = db.run {
    (users.map(u => (u.name, u.email))
      returning users.map(_.id)
      into ((nameEmail, id) => User(id, nameEmail._1, nameEmail._2))
    ) += (name, email)
  }

  def list(): Future[Seq[User]] = db.run {
    users.result
  }
}
```

This setup allows you to perform database operations using Scala code, which is type-safe and composable.

## Handling Errors and Checking Input

When building a REST API with Scala Play Framework, proper error handling and input validation are crucial for creating a robust and secure application.

### Managing Errors

To handle errors effectively in your API:

1.  Implement a custom error handler by creating a class that extends `HttpErrorHandler`:

```scala
import play.api.http.HttpErrorHandler
import play.api.mvc._
import scala.concurrent._

class CustomErrorHandler extends HttpErrorHandler {
  def onClientError(request: RequestHeader, statusCode: Int, message: String): Future[Result] = {
    Future.successful(
      Status(statusCode)("A client error occurred: " + message)
    )
  }

  def onServerError(request: RequestHeader, exception: Throwable): Future[Result] = {
    Future.successful(
      InternalServerError("A server error occurred: " + exception.getMessage)
    )
  }
}
```

2.  Configure your custom error handler in `application.conf`:

```hocon
play.http.errorHandler = "com.example.CustomErrorHandler"
```

### Checking Input Data

To validate input data:

1.  Use case classes for your data models:

```scala
case class User(name: String, email: String, age: Int)
```

2.  Implement validation logic:

```scala
import play.api.data.validation.{Constraint, Invalid, Valid, ValidationError}

object UserValidation {
  val emailRegex = """^[a-zA-Z0-9\.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$""".r

  def validateEmail: Constraint[String] = Constraint("constraints.email")({ email =>
    if (email.matches(emailRegex.regex)) Valid
    else Invalid(ValidationError("Invalid email format"))
  })

  def validateAge: Constraint[Int] = Constraint("constraints.age")({ age =>
    if (age >= 18 && age <= 120) Valid
    else Invalid(ValidationError("Age must be between 18 and 120"))
  })
}
```

3.  Use validation in your controller:

```scala
import play.api.mvc._
import play.api.libs.json._

class UserController extends Controller {
  def createUser = Action(parse.json) { request =>
    val userResult = request.body.validate[User]
    userResult.fold(
      errors => {
        BadRequest(Json.obj("message" -> JsError.toJson(errors)))
      },
      user => {
        if (UserValidation.validateEmail(user.email).isValid && UserValidation.validateAge(user.age).isValid) {
          // Process valid user
          Ok(Json.obj("message" -> "User created successfully"))
        } else {
          BadRequest(Json.obj("message" -> "Invalid user data"))
        }
      }
    )
  }
}
```

## Testing Your API

Testing your REST API built with Scala Play Framework is crucial to ensure it works correctly and reliably. Let's explore three key testing approaches:

### Writing Unit Tests

Unit tests focus on individual components of your API, typically at the method level. For Scala Play, you can use [ScalaTest](https://www.scalatest.org/) with Play:

1.  Add ScalaTest to your `build.sbt`:

```scala
libraryDependencies ++= Seq("org.scalatestplus.play" %% "scalatestplus-play" % "5.1.0" % Test)
```

2.  Create a test class in the `test` folder:

```scala
import org.scalatestplus.play._
import play.api.test._
import play.api.test.Helpers._

class UserControllerSpec extends PlaySpec with Results {
  "UserController GET" should {
    "return a list of users" in {
      val controller = new UserController(Helpers.stubControllerComponents())
      val result = controller.list().apply(FakeRequest())
      status(result) mustBe OK
      contentType(result) mustBe Some("application/json")
      contentAsString(result) must include("John Doe")
    }
  }
}
```

This test checks if the `list()` method in `UserController` returns a 200 OK status and includes expected content.

### Testing the Whole System

Integration tests verify how different parts of your API work together. Play provides tools for this:

1.  Use `WithApplication` to test with a full application context:

```scala
"Application" should {
  "work from within a browser" in new WithBrowser {
    browser.goTo("/")
    browser.pageSource must contain("Welcome to Play")
  }
}
```

2.  Test database interactions:

```scala
"UserRepository" should {
  "save and retrieve a user" in new WithApplication {
    val repo = app.injector.instanceOf[UserRepository]
    val user = User("Alice", "alice@example.com")
    await(repo.create(user))
    val retrieved = await(repo.findByEmail("alice@example.com"))
    retrieved.map(_.name) mustBe Some("Alice")
  }
}
```

### Using API Test Tools

External tools can help test your API endpoints:

1.  **[Postman](https://www.postman.com/)**: Create a collection for your API:
    
    -   Set up environment variables for your API URL
    -   Create requests for each endpoint
    -   Write tests for responses:
    
    ```javascript
    pm.test("Status code is 200", function () {
        pm.response.to.have.status(200);
    });
    
    pm.test("Body contains users", function () {
        var jsonData = pm.response.json();
        pm.expect(jsonData.users).to.be.an('array');
    });
    ```
    
2.  **cURL**: Test endpoints from the command line:
    
    ```bash
    curl -X GET http://localhost:9000/api/users \
    -H "Content-Type: application/json"
    ```
    
3.  **[Automated API testing](https://daily.dev/blog/automated-vs-manual-api-testing-key-differences)**: Integrate API tests into your [CI/CD pipeline](https://daily.dev/blog/cicd-pipeline-orchestration-complete-guide-2024) using tools like Newman (Postman's CLI runner) or custom scripts.
    

## Adding Security

Securing your Scala Play Framework REST API is crucial to protect sensitive data and prevent unauthorized access. Let's explore three key security measures:

### Simple Password Protection

To add basic password protection to your API endpoints:

1.  Create a custom action in your controller:

```scala
def withBasicAuth(action: Action[AnyContent]) = Action.async { request =>
  request.headers.get("Authorization") match {
    case Some(auth) if auth == "Basic " + Base64.getEncoder.encodeToString("username:password".getBytes) =>
      action(request)
    case _ =>
      Future.successful(Unauthorized("Invalid credentials"))
  }
}
```

2.  Apply this action to your endpoints:

```scala
def secureEndpoint = withBasicAuth {
  Action { implicit request =>
    Ok("Secure content")
  }
}
```

This method is simple but not suitable for production use due to its limitations in scalability and security.

### Using Tokens for Security

JSON Web Tokens (JWT) offer a more robust, stateless authentication method:

1.  Add the JWT library to your `build.sbt`:

```scala
libraryDependencies += "com.pauldijou" %% "jwt-play" % "5.0.0"
```

2.  Create a JWT helper:

```scala
import pdi.jwt.{JwtAlgorithm, JwtJson}
import play.api.libs.json.Json

object JwtHelper {
  private val secretKey = "your-secret-key"
  private val algorithm = JwtAlgorithm.HS256

  def createToken(userId: String): String = {
    val claim = Json.obj("user_id" -> userId)
    JwtJson.encode(claim, secretKey, algorithm)
  }

  def validateToken(token: String): Option[String] = {
    JwtJson.decodeJson(token, secretKey, Seq(algorithm)).toOption.flatMap { claim =>
      (claim \ "user_id").asOpt[String]
    }
  }
}
```

3.  Implement token-based authentication in your controller:

```scala
def secureEndpoint = Action.async { request =>
  request.headers.get("Authorization") match {
    case Some(auth) if auth.startsWith("Bearer ") =>
      val token = auth.substring(7)
      JwtHelper.validateToken(token) match {
        case Some(userId) =>
          // Proceed with the authenticated request
          Future.successful(Ok(s"Authenticated user: $userId"))
        case None =>
          Future.successful(Unauthorized("Invalid token"))
      }
    case _ =>
      Future.successful(Unauthorized("Missing or invalid Authorization header"))
  }
}
```

### Controlling Who Can Do What

Implement role-based access control (RBAC) to manage user permissions:

1.  Define user roles and permissions in your database schema.
    
2.  Create a custom action to check user roles:
    

```scala
def withRole(role: String)(action: Action[AnyContent]) = Action.async { request =>
  request.headers.get("Authorization") match {
    case Some(auth) if auth.startsWith("Bearer ") =>
      val token = auth.substring(7)
      JwtHelper.validateToken(token) match {
        case Some(userId) =>
          // Check user role in the database
          userRepository.getUserRole(userId).flatMap {
            case Some(`role`) => action(request)
            case _ => Future.successful(Forbidden("Insufficient permissions"))
          }
        case None =>
          Future.successful(Unauthorized("Invalid token"))
      }
    case _ =>
      Future.successful(Unauthorized("Missing or invalid Authorization header"))
  }
}
```

3.  Apply role-based access to your endpoints:

```scala
def adminOnlyEndpoint = withRole("admin") {
  Action { implicit request =>
    Ok("Admin-only content")
  }
}
```

## Making Your API Faster

To boost your Scala Play Framework REST API's speed, focus on these key areas:

### Using Async Programming

Scala Futures allow non-blocking operations, improving API response times. Here's how to implement them:

1.  Add the scala-async library to your `build.sbt`:

```scala
libraryDependencies += "org.scala-lang.modules" %% "scala-async" % "1.0.1"
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided
scalacOptions += "-Xasync"
```

2.  Use `async` and `await` for asynchronous operations:

```scala
def parallelComputation: Future[Int] = async { 
  val r1 = slowComputation 
  val r2 = anotherSlowComputation("Data")
  await(r1) + await(r2)
}
```

This approach allows for parallel execution, reducing overall response time.

### Adding Caching

Caching cuts down database calls, speeding up responses for often-requested data. Implement caching in your Play application:

1.  Add the Play cache dependency to your `build.sbt`:

```scala
libraryDependencies += ehcache
```

2.  Use the cache in your controller:

```scala
import play.api.cache._

class MyController @Inject()(cache: SyncCacheApi) extends Controller {
  def getData = Action {
    cache.getOrElseUpdate("my-key") {
      // Expensive operation here
      expensiveDataFetch()
    }
    Ok("Data retrieved")
  }
}
```

This caches the result of `expensiveDataFetch()`, serving it quickly on subsequent requests.

### Speeding Up Database Queries

Optimize your database queries to enhance API performance:

1.  Use indexes for columns in WHERE, JOIN, and ORDER BY clauses.
2.  Employ parameterized queries to avoid recompiling execution plans.
3.  Consider stored procedures for common queries.

Example of a slow query improved by indexing:

```sql
-- Before (28 seconds execution time)
SELECT * FROM large_table WHERE non_indexed_column = 'value'

-- After adding index (32 milliseconds execution time)
CREATE INDEX idx_non_indexed_column ON large_table(non_indexed_column);
SELECT * FROM large_table WHERE non_indexed_column = 'value'
```

## Putting Your API Online

Getting your Scala Play Framework REST API ready for real-world use involves careful preparation and deployment. Let's explore how to set up your application for production and the various ways to deploy it.

### Setting Up for Production

Before deploying your API, you need to adjust several settings for the live environment:

1\. **Configuration Changes**

Play uses various `.conf` files for configuration, primarily `application.conf` in the `conf/` directory. For production, override specific settings:

```scala
# Production database URL
db.default.url="jdbc:postgresql://production-db-host/myapp"

# Application secret (generate a new one for production)
play.http.secret.key="abcdefghijk123456789"

# HTTP port (often set by the hosting environment)
http.port=9000
```

You can also use system properties or environment variables to change settings dynamically:

```bash
$ bin/your-app -Dhttp.port=9081 -Dhttp.address=192.168.1.10
```

2\. **Packaging Your Application**

To create a production-ready package:

```bash
$ sbt clean dist
```

This command generates a ZIP file in `target/universal/` containing all necessary JAR files.

3\. **[Performance Tuning](https://daily.dev/blog/performance-boosting-tips-for-developers)**

Optimize your application's performance:

-   Increase Akka thread pool size for database-driven apps:

```scala
akka {
  actor {
    default-dispatcher {
      fork-join-executor {
        parallelism-factor = 3.0
        parallelism-max = 64
      }
    }
  }
}
```

-   Use asynchronous programming where possible to leverage Play's non-blocking architecture.

### Ways to Deploy

There are several options for deploying your Scala Play Framework API:

1\. **Heroku Deployment**

Heroku offers a straightforward deployment process:

-   Add the Heroku sbt plugin to `project/plugins.sbt`:

```scala
addSbtPlugin("com.heroku" % "sbt-heroku" % "2.1.4")
```

-   Set your app name in `build.sbt`:

```scala
herokuAppName in Compile := "your-app-name"
```

-   Deploy with:

```bash
$ sbt stage deployHeroku
```

2\. **Manual Server Deployment**

For more control, deploy manually to your server:

-   Upload the distribution package to your server.
-   Unzip and run the start script:

```bash
$ unzip your-app-1.0.zip
$ your-app-1.0/bin/your-app -Dplay.http.secret.key=your-secret-key
```

3\. **Docker Deployment**

Containerize your application for consistent deployments:

-   Create a `Dockerfile` in your project root:

```dockerfile
FROM openjdk:11-jre-slim
COPY target/universal/stage /app
WORKDIR /app
CMD ["bin/your-app", "-Dplay.http.secret.key=your-secret-key"]
```

-   Build and run your Docker image:

```bash
$ docker build -t your-app .
$ docker run -p 9000:9000 your-app
```

## Wrapping Up

### Key Points to Remember

Building a REST API with Scala Play Framework involves several crucial steps:

-   **Project setup**: Use SBT and Giter8 templates to scaffold your project quickly.
-   **API design**: Plan your endpoints, data models, and HTTP methods carefully.
-   **Security**: Implement access token validation using services like [Auth0](https://auth0.com/identity-platform).
-   **Testing**: Regularly test your API with tools like `curl` to ensure proper functionality.
-   **Performance**: Use async programming and caching to boost API speed.

### Tips for Good APIs

1.  **Encrypt all communications**: Protect sensitive data in transit.
2.  **Authenticate users**: Use API keys or OAuth 2 for all API calls.
3.  **Monitor usage**: Keep detailed logs for debugging and security.
4.  **Validate input**: Prevent SQL injection and other attacks.
5.  **Implement rate limiting**: Protect against DDoS attacks with throttling and quotas.

### Where to Learn More

To deepen your Scala and Play Framework knowledge:

-   **Official documentation**: Play Framework and Scala websites offer comprehensive guides.
-   **Online courses**: Platforms like [Coursera](https://www.coursera.org/) and [Udemy](https://www.udemy.com/) provide in-depth Scala courses.
-   **Community forums**: [Stack Overflow](https://stackoverflow.com/) and Reddit's r/scala are great for problem-solving.
-   **Books**: "Play for Scala" by Peter Hilton et al. offers practical insights.

```json
{"@context":"https://schema.org","@graph":[{"@type":"Organization","@id":"https://daily.dev/#organization","name":"daily.dev","url":"https://daily.dev","logo":{"@type":"ImageObject","url":"https://daily.dev/og-image.png?v=a830cdf1","width":1200,"height":630},"sameAs":["https://twitter.com/dailydotdev","https://www.linkedin.com/company/dailydotdev","https://github.com/dailydotdev","https://www.instagram.com/dailydotdev"]},{"@type":"WebSite","@id":"https://daily.dev/#website","url":"https://daily.dev","name":"daily.dev","description":"Free, personalized developer news aggregator. Stay on top of software development news, AI coding tools, and web dev - curated daily from trusted sources.","publisher":{"@id":"https://daily.dev/#organization"},"potentialAction":{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https://daily.dev/search?q={search_term_string}"},"query-input":"required name=search_term_string"}},{"@type":"WebPage","@id":"https://daily.dev/blog/build-rest-api-with-scala-play-framework/","url":"https://daily.dev/blog/build-rest-api-with-scala-play-framework/","name":"Build REST API with Scala Play Framework | daily.dev","description":"Learn how to build a robust REST API using Scala and Play Framework, covering setup, security, performance, and deployment strategies.","inLanguage":"en-US","isPartOf":{"@id":"https://daily.dev/#website"},"timeRequired":"PT16M"},{"@type":"Article","@id":"https://daily.dev/blog/build-rest-api-with-scala-play-framework/#article","headline":"Build REST API with Scala Play Framework","url":"https://daily.dev/blog/build-rest-api-with-scala-play-framework/","datePublished":"2024-09-05","dateModified":"2026-05-25T06:17:33.264Z","isPartOf":{"@id":"https://daily.dev/#website"},"publisher":{"@id":"https://daily.dev/#organization"},"mainEntityOfPage":{"@type":"WebPage","@id":"https://daily.dev/blog/build-rest-api-with-scala-play-framework/"},"description":"Learn how to build a robust REST API using Scala and Play Framework, covering setup, security, performance, and deployment strategies.","image":{"@type":"ImageObject","url":"https://media.daily.dev/image/upload/s--l6RvOb41--/f_auto,q_auto/v1/recruiter-landing/66d8f632626438aa32fb868a_224aa26f9f3eb6538ad7962c9c952d0b_06fe962871?_a=BAMAMiB80"},"author":{"@type":"Person","name":"Alex Carter","url":"https://app.daily.dev/alexcarterdev"},"timeRequired":"PT16M","potentialAction":{"@type":"ReadAction","target":"https://daily.dev/blog/build-rest-api-with-scala-play-framework/"}},{"@type":"BreadcrumbList","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https://daily.dev/"},{"@type":"ListItem","position":2,"name":"Blog","item":"https://daily.dev/blog/"},{"@type":"ListItem","position":3,"name":"Backend","item":"https://daily.dev/categories/backend/"},{"@type":"ListItem","position":4,"name":"Build REST API with Scala Play Framework","item":"https://daily.dev/blog/build-rest-api-with-scala-play-framework/"}]}]}
```

