Feature Toggle is the capability for an application, a system or a product to enable and/or disable features through configuration (files, databases,...) and possibly at runtime. FF4J, stands as Feature Flipping for Java, is an implementation of this pattern for the Java platform.

Embedded WebConsole

Toggle features at runtime through dedicated embedded console. A single servlet declaration is required in web.xml

Multiple persistance storage

Persist your features into external storage to keep and share a state of your system. Several implementations are available.

Permissions Management

Toggle your features for a subset of users. (canary release). Several security providers implementations are available.

Feature Strategies

Implement your own behaviour to decide if a feature is on. Predicate is evaluated if status is enabled and user granted (optional).

Toggling through AOP

Avoid nested if statements everywhere but decorate your code with annotations. Inversion of control is overrided to choose correct implementation.


Operate your features through (secure) REST API wich allow any clients like JAVASCRIPT of MOBILE APPLICATIONS

Caching Management

Limit overread of quering external storages by caching. Several distributed cache implementations are already available.


Not all applications are web-oriented. You can now operate your features through dedicated JMX console if required.


Features usage is monitored in the same time as checking for toggling. The metrics could be visualized through dedicated dashboards.

Full Stack Console

Provide a full-stack console, much complete than embedded which interact with target through the REST API

10 min tutorial

Hello World !

In this section we will create a sample from scratch, skip first steps if you already have a working project. First, create a simple web project with dedicated maven archetype. We could have chosen a basic archetype but we could like to show you the web console.

mvn archetype:generate -DarchetypeArtifactId=maven-archetype-webapp \
	               -Dversion=1.0 -DartifactId=hello-ff4j -DgroupId=org.ff4j.hello

Import the project in your favorite IDE, open your pom.xml file and add the following dependencies. JUNIT should already be provided but with a quite old version.



If required, the maven project folders (src/main/java, src/test/java....). In the folder src/test/resources, create the following ff4j.xml file. We should have put you a single feature but let's illustrate immediately some great capabilities.

<?xml version="1.0" encoding="UTF-8" ?>
<features xmlns="http://ff4j.org/schema" 
     xsi:schemaLocation="http://ff4j.org/schema http://ff4j.org/schema/ff4j-1.2.0.xsd">

  <!-- Will be "ON" if enable is set as true -->
  <feature uid="hello" enable="true"  description="This is my firts feature" />
  <!-- Will be "ON" only if :
   (1) Enable is set as true
   (2) A security provider is defined  
   (3) The current logged user has the correct permissions. -->
  <feature uid="mySecuredFeature" enable="true" >
	<role name="USER" />
	<role name="ADMIN" />
  <!-- Will be "ON" only if 
   (1) Enable is set as true
   (2) Strategy predicate is true (here current > releaseDate) -->
  <feature uid="myFutureFeature" enable="true">
    <flipstrategy class="org.ff4j.strategy.ReleaseDateFlipStrategy" >
      <param name="releaseDate" value="2020-07-14-14:00" />
  <!-- Features can be grouped to be toggled in the same time -->
  <feature-group name="sprint_3">
    <feature uid="userStory3_1" enable="false" />
    <feature uid="userStory3_2" enable="false" />

In the src/test/java, create the package org.ff4j.hello with the following JUNIT class. We put several use cases to give you an overview. As I use to say, a piece of code is much clear than a long paragraph.

package org.ff4j.hello;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import org.ff4j.FF4j;
import org.ff4j.exception.FeatureNotFoundException;
import org.junit.Test;

public class HelloTest {
    public void my_first_test() {
        // Given: file exist
        // When: init
        FF4j ff4j = new FF4j("ff4j.xml");
        // Then
        assertEquals(5, ff4j.getFeatures().size());
        // Usage
        if (ff4j.check("hello")) {
            // hello is toggle on
            System.out.println("Hello World !!");
        // When: Toggle Off
        // Then: expected to be off
    public void how_does_AutoCreate_Works() {
        // Given: feature not exist
        FF4j ff4j = new FF4j("ff4j.xml");
        // When: use it
        try {
           if (ff4j.check("does_not_exist")) fail();
        } catch (FeatureNotFoundException fnfe) {
            // Then: exception
            System.out.println("By default, feature not found throw exception");
        // When: using autocreate
        // Then: no more exceptions
        if (!ff4j.check("does_not_exist")) {
            System.out.println("Auto created and set as false");
    public void how_groups_works() {
        // Given: 2 features 'off' within existing group
        FF4j ff4j = new FF4j("ff4j.xml");
        assertEquals("sprint_3", ff4j.getFeature("userStory3_1").getGroup());
        assertEquals("sprint_3", ff4j.getFeature("userStory3_2").getGroup());
        // When: toggle group on
        // Then: all features on

Web Console

In production you probably won't toggle Off your features programmatically (maybe to implement a circuit breaker), instead you will toggle features through web console.

FF4J provided 2 consoles : one is embedded as a servlet, the other is a full-stack application (operating with remote components through REST API). Here we will demonstrate the usage of the embedded. Add the following dependencies to your pom.xml file.


The, add the following statement within <build> tag. The purpose here is to execute our web application on jetty container using the proper maven plugin. We also add src/test/resource to jetty classpath, where we created the ff4j.xml file.


    <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">

You should be able to start your application with mvn jetty:run and access URL http://localhost:8080/hello/

The administration console needs to find the instance of FF4j to operate features. You have to define a class implementing org.ff4j.web.api.FF4JProvider and reference it when declaring the servlet.

Create a class MyFF4JProvider in src/main/java in the package of your choice with the following source code. Note that the single expected method is getFF4j()

package org.ff4j.hello;

import org.ff4j.FF4j;
import org.ff4j.web.api.FF4JProvider;

public class MyFF4jProvider implements FF4JProvider {

    private final FF4j ff4j;
    public MyFF4jProvider() {
        ff4j = new FF4j("ff4j.xml");
    /** {@inheritDoc} */
    public FF4j getFF4j() { return ff4j; }
Note : If your are working with any dependency injection framework like Spring Framework you will probably inject ff4j as a bean it, but, here, we want to avoid any dependency.

Update your web.xml file and declare the servlet like the following :
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"

 <display-name>HelloWorld ff4j app</display-name>
   <welcome-file>index.jsp </welcome-file>


You should be able access administration console http://localhost:8080/hello/ff4j-console

Every operation performed through this console are performed in-memory. At next restart, the state will be lost. To avoid this behavior you will need to change the FeatureStore and choose among JDBC, MongoDB or Redis.

The code of this sample (and many others) is available on github HERE

What's NEXT ?

This following introduction is the simplest code ever. A real getting started guide is available on github and deals with integration with Spring, AOP and externalization to JDBC. The reference guide contains all informations related to the framework. Finally there are a lot of samples available on github. At end, don't hesitate to raise your question to support google group

Some Use Cases

Avoid Feature Branching

Feature branches lead to conflict during merges. Use trunk-based-developpement to toggle-off unfinished code when develop continously.

Blue/Green Deployments

Avoid clusters nodes inconsistency during deployment and deliver new features desactivated. Toggle "ON"" when all nodes are up-to-date and ready.

Canary Release

Do not create dedicated infrastructure to qualify new features. Open them for subset of beta-testers and directly into production environments.

Dark Launch

Measure performance impacts of new features. Activate them dynamically on a defined ratio of incoming requests and observe system responses.

Graceful degradation

Tune and protect your system of heavy loads: focus on high business value requests and discard others dynamically (clients vs prospects, carts contents..).

Thin client application

Avoid annoying frequent deployments and downloads of mobile applications by providing empty shelf: request expected active features to YOUR servers.

Business Toggle

Toggling is not only technical. Define your own rules and evaluate features based on business requirements like office hours, user profiles...

A/B Testing

Split A and B populations using a business toggle. Measure business impacts not only with CRM but also hitcounts of very same framework.

Circuit Breaker

Implement the circuit breaker pattern with a dedicated strategy and custom rules allowing to toggle off proactively not available features.

Fork me on GitHub