Skip to content
Switch branches/tags


Failed to load latest commit information.
Latest commit message
Commit time

View performance data on Skylight

Apply for teacher training

A service for candidates to apply for teacher training. We're currently in private beta.

Screenshot of the candidate-facing interface

Live environments

Name URL Description PaaS space PaaS application
Production www Public site bat-prod apply-prod
Sandbox sandbox Demo environment for software vendors who integrate with our API bat-prod apply-sandbox
Staging staging For internal use by DfE to test deploys bat-staging apply-staging
QA qa For internal use by DfE for testing. Automatically deployed from main bat-qa apply-qa

Table of Contents


We keep track of the things we learn:

How the application works

The application has a number of different interfaces for different types of users:

Diagram of the Apply interfaces


Diagram of the technical architecture

We keep track of architecture decisions in Architecture Decision Records (ADRs).

An overview of the PaaS hosted infrastructure architecture can be found in the PaaS Infrastructure document.

Domain Model

The domain model for this application

For simplicity the auditing table is not displayed in the diagram, as it is connected to most tables in the database.

Regenerate this diagram with bundle exec rake erd.

Application states

All of the states and transitions in the app

Regenerate this diagram with bundle exec rake generate_state_diagram.


Production dependencies

Development dependencies

There are two ways to run the application in development. Running a local development environment is the most common approach but it is also possible to run in local Docker containers.

Development environment

Running the application with local dependencies

The most common way to run a development version of the application is run with local dependencies.

Local development dependencies

  • postgresql
  • redis
  • Graphviz 2.22+ (brew install graphviz) to generate the domain model diagram
  • ruby
  • nodejs
  • chromedriver (you will need chromedriver and a version of Chrome installed to run the full test suite)

The recommended way to install language runtimes (ie Ruby and Node) is using the asdf version manager tool (documentation). asdf considers a file called .tool-versions in the repository root when deciding which version of each language to install or use.

On a mac:

# The first time
brew install asdf
asdf plugin add ruby
asdf plugin add nodejs
asdf plugin add yarn

# To install (or update, following a change to .tool-versions)
asdf install

You'll also need to copy .env.example to .env and fill in the secrets. This will populate required environment variables

Once those dependencies are installed, run bundle install to install required gems.

Local db setup

  1. Start the postgres service: sudo service postgresql start on Linux or brew services start postgresql on Mac
  2. Populate the DB_ relevant environment variables with the correct values (those are: DB_USERNAME, DB_PASSWORD, DB_HOSTNAME and DB_PORT)
  3. Then local development databases and data can be set up: bundle exec rake db:setup (You may wish to set up development data at this point)

Running the app

To run the application locally:

  1. Run yarn to install dependencies for the web app to run
  2. Run foreman start to launch the app on http://localhost:3000

Running the application in Docker

As an alternative to that, it's also possible to run the application in Docker:

Docker dependencies

Running the app

Install the above dependencies, and then:

  1. Copy .env.example to .env and fill in the secrets
  2. Run make setup
  3. Run make serve to launch the app on https://localhost:3000

See Makefile for the steps involved in building and running the app.

Development data

The course and training provider data in the Apply service comes from its sister service Publish. To populate your local database with course data from Publish, first start the redis service (redis-server) and then run bundle exec rake setup_local_dev_data.

Among other things, this task also creates a support user with DfE Sign-in UID dev-support that you can use to sign in to the Support interface in your development environment, and a provider user with the UID dev-provider.

Background processing

Certain features depend on Sidekiq running. e.g. Mailers and some of the business rules that set time-dependent state on applications. In order to run a local version of Sidekiq you need to make sure Redis is installed and running and then run Sidekiq. The simplest way to do that is with docker-compose (see below) or foreman. e.g.

$ foreman start

Docker Workflow

Under docker-compose, the database uses a Docker volume to persist storage across docker-compose ups and docker-compose downs. For want of cross-platform compatibility between JavaScript libraries, the app's node_modules folder is also stored in a persistent Docker volume.

Running make setup will blow away and recreate those volumes, destroying any data you have created in development. It is necessary to run it at least once before the app will boot in Docker.

DfE Sign-in

The Provider interface at /provider and Support interface at /support are both protected by DfE's SSO provider DfE Sign-in.


In development and QA we use the Test environment of DfE Sign-in:

Manage console (test)

# .env

In staging, production and sandbox we use the Production environment of DfE Sign-in:

Manage console (production)

# .env

Local development

Creating and signing in to the candidate interfaces requires clicking a link sent via email using GOV.UK Notify.

In development mode, the contents of the emails sent is saved to a log file, which you can see by running:

tail -f log/mail.log

Signing in to the Provider interface requires a network connection and a user account on DfE Sign-in. In development you can eliminate this dependency by setting BYPASS_DFE_SIGN_IN=true in your .env file. This replaces the sign in flow with a dialog allowing you to specify a DfE Sign-in UID and Email address for your current session.

Provider permissions

We decide what to show providers based on their DfE Sign-in UID.

To grant a user permission to view a provider’s applications, visit /support/users/providers and create a user, specifying their DfE Sign-in UID and the relevant provider.

Support permissions

There is a support_users database table that lists all the DfE Sign-in accounts that have access to the Support interface based on their DfE Sign-in UID. There is only one privilege level, either you have access to everything or nothing.

You can add a new support user using the create_support_user rake task. You need to supply a DfE Sign-in UID and an email address, e.g.

$ bundle exec rails "create_support_user[alice,]"

Note that only the UID is used for lookup. The email address serves only as a label.

Review apps

When a new PR is opened, you have the option to deploy a review app into the bat-qa space. A deployment is initiated by adding the deploy label either when the PR is created or retrospectively. The app is destroyed when the PR is closed.

Review apps have HOSTING_ENVIRONMENT set to review, an empty database which gets seeded with local dev data, and a URL which will be https://apply-review-{PR_NUMBER}

Management of review apps follow the same processes as our standard PaaS based apps.


MIT Licence