Skip to content
← All insights
Play Framework5 min read

Common problems in long-lived Play Framework applications

The Play version gets the blame, but the real trouble is often hiding elsewhere.

Skipped upgrades add up

Miss a few Play, Scala and sbt releases and the eventual jump gets much wider. Plugins vanish, APIs move and an old JDK starts dictating where the service can run.

Look past the controllers

Slow builds, giant integration tests, blocking database calls and muddled service boundaries often hurt more than the framework version itself.

  • Find blocking work and check its execution context
  • Treat JSON changes as API changes
  • Reduce global state where it blocks testing
  • Make configuration failures obvious at startup
Keep blocking work off Play’s default dispatcherscala
def findUser(id: UserId) = Action.async {
  Future(blocking(repository.find(id)))(databaseEc)
    .map {
      case Some(user) => Ok(Json.toJson(user))
      case None       => NotFound
    }
}

Give yourself checkpoints

Map the important dependencies and protect the busiest user journeys before you begin. Upgrade in stages you can run and observe. It is much easier to find a bad change when it travelled alone.