Creating the basic structure of the proposal sent by mail
diff --git a/README.md b/README.md
index e7ed37f..97588dd 100644
--- a/README.md
+++ b/README.md
@@ -76,4 +76,10 @@
 }
 
 
-```
\ No newline at end of file
+```
+
+## Dev tip
+
+To find the interceptor priority you can use this shell command:
+
+`find . -name *Interceptor.java | xargs grep '@Priority'  | sed 's/\([^:]*\):\(.*\)/\2 : \1/g' | sed 's/@Priority(Interceptor.Priority.PLATFORM_AFTER + \([0-9]*\))/priority = \1/' | sort`
diff --git a/pom.xml b/pom.xml
index 882c30f..f85ac1f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -29,11 +29,12 @@
     <artifactId>safeguard-parent</artifactId>
     <version>1.1-SNAPSHOT</version>
     <packaging>pom</packaging>
+    <name>Apache Safeguard</name>
+
     <modules>
-        <module>safeguard-api</module>
         <module>safeguard-impl</module>
-        <module>safeguard-tck-tests</module>
     </modules>
+
     <licenses>
         <license>
             <name>Apache License, Version 2.0</name>
@@ -72,30 +73,19 @@
     <properties>
         <maven.compiler.source>1.8</maven.compiler.source>
         <maven.compiler.target>1.8</maven.compiler.target>
-        <microprofile-fault-tolerance.version>1.0</microprofile-fault-tolerance.version>
+        <microprofile-fault-tolerance.version>1.1.3</microprofile-fault-tolerance.version>
         <owb.version>2.0.1</owb.version>
         <arquillian.version>1.1.14.Final</arquillian.version>
         <arquillian-weld-embedded.version>2.0.0.Final</arquillian-weld-embedded.version>
         <cdi2-api.version>2.0</cdi2-api.version>
         <weld.version>3.0.1.Final</weld.version>
-        <geronimo-config-impl.version>1.1</geronimo-config-impl.version>
+        <geronimo-config-impl.version>1.2</geronimo-config-impl.version>
         <microprofile-config-api.version>1.2</microprofile-config-api.version>
-        <failsafe.version>1.0.4</failsafe.version>
     </properties>
 
     <dependencyManagement>
         <dependencies>
             <dependency>
-                <groupId>org.apache.geronimo.safeguard</groupId>
-                <artifactId>safeguard-api</artifactId>
-                <version>${project.version}</version>
-            </dependency>
-            <dependency>
-                <groupId>net.jodah</groupId>
-                <artifactId>failsafe</artifactId>
-                <version>${failsafe.version}</version>
-            </dependency>
-            <dependency>
                 <groupId>org.apache.geronimo.specs</groupId>
                 <artifactId>geronimo-jcdi_2.0_spec</artifactId>
                 <version>1.0.1</version>
diff --git a/safeguard-api/pom.xml b/safeguard-api/pom.xml
deleted file mode 100644
index 8ba6b83..0000000
--- a/safeguard-api/pom.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~  Licensed to the Apache Software Foundation (ASF) under one
-  ~  or more contributor license agreements.  See the NOTICE file
-  ~  distributed with this work for additional information
-  ~  regarding copyright ownership.  The ASF licenses this file
-  ~  to you under the Apache License, Version 2.0 (the
-  ~  "License"); you may not use this file except in compliance
-  ~  with the License.  You may obtain a copy of the License at
-  ~
-  ~  http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~  Unless required by applicable law or agreed to in writing,
-  ~  software distributed under the License is distributed on an
-  ~  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~  KIND, either express or implied.  See the License for the
-  ~  specific language governing permissions and limitations
-  ~  under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>safeguard-parent</artifactId>
-        <groupId>org.apache.geronimo.safeguard</groupId>
-        <version>1.1-SNAPSHOT</version>
-    </parent>
-    <name>Apache Safeguard :: API</name>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>safeguard-api</artifactId>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcdi_2.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-annotation_1.3_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-interceptor_1.2_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.eclipse.microprofile.fault-tolerance</groupId>
-            <artifactId>microprofile-fault-tolerance-api</artifactId>
-        </dependency>
-    </dependencies>
-</project>
\ No newline at end of file
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/ExecutionManager.java b/safeguard-api/src/main/java/org/apache/safeguard/api/ExecutionManager.java
deleted file mode 100644
index 1061043..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/ExecutionManager.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api;
-
-import org.apache.safeguard.api.bulkhead.BulkheadManager;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerManager;
-import org.apache.safeguard.api.retry.RetryManager;
-
-import javax.interceptor.InvocationContext;
-import java.util.concurrent.Callable;
-
-public interface ExecutionManager {
-    <T> T execute(String name, Callable<T> callable);
-
-    Object execute(InvocationContext invocationContext);
-
-    CircuitBreakerManager getCircuitBreakerManager();
-
-    RetryManager getRetryManager();
-
-    BulkheadManager getBulkheadManager();
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/Bulkhead.java b/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/Bulkhead.java
deleted file mode 100644
index 5675a6d..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/Bulkhead.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.bulkhead;
-
-import java.util.concurrent.Callable;
-
-public interface Bulkhead {
-    BulkheadDefinition getBulkheadDefinition();
-
-    int getCurrentQueueDepth();
-
-    int getCurrentExecutions();
-
-    <T> T execute(Callable<T> callable);
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/BulkheadBuilder.java b/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/BulkheadBuilder.java
deleted file mode 100644
index 19f7bdc..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/BulkheadBuilder.java
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.bulkhead;
-
-public interface BulkheadBuilder {
-    BulkheadBuilder withMaxConcurrency(int maxConcurrency);
-
-    BulkheadBuilder withMaxWaiting(int overflowCapacity);
-
-    BulkheadBuilder asynchronous();
-
-    BulkheadDefinition build();
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/BulkheadDefinition.java b/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/BulkheadDefinition.java
deleted file mode 100644
index bb7e942..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/BulkheadDefinition.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.bulkhead;
-
-public interface BulkheadDefinition {
-    int getMaxConcurrentExecutions();
-
-    int getMaxWaitingExecutions();
-
-    boolean isAsynchronous();
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/BulkheadManager.java b/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/BulkheadManager.java
deleted file mode 100644
index 3b155ad..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/bulkhead/BulkheadManager.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.bulkhead;
-
-public interface BulkheadManager {
-    BulkheadBuilder newBulkheadBuilder(String name);
-    Bulkhead getBulkhead(String name);
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreaker.java b/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreaker.java
deleted file mode 100644
index cce9b11..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreaker.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.circuitbreaker;
-
-public interface CircuitBreaker {
-    CircuitBreakerDefinition getDefinition();
-    CircuitBreakerState getState();
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerBuilder.java b/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerBuilder.java
deleted file mode 100644
index c20a426..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerBuilder.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.circuitbreaker;
-
-import org.apache.safeguard.api.retry.RetryBuilder;
-import org.apache.safeguard.api.retry.RetryDefinition;
-
-import java.time.Duration;
-
-public interface CircuitBreakerBuilder {
-    CircuitBreakerBuilder withDelay(Duration delay);
-    CircuitBreakerBuilder withFailureCount(int failureCount);
-    CircuitBreakerBuilder withFailures(int failureCount, int requestCount);
-    CircuitBreakerBuilder withSuccessCount(int successCount);
-    CircuitBreakerBuilder withSuccesses(int successCount, int requestCount);
-    CircuitBreakerBuilder withFailOn(Class<? extends Throwable>... failOn);
-
-    CircuitBreakerDefinition build();
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerDefinition.java b/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerDefinition.java
deleted file mode 100644
index 7780ece..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerDefinition.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.circuitbreaker;
-
-import javax.enterprise.util.Nonbinding;
-import java.time.Duration;
-import java.time.temporal.ChronoUnit;
-import java.util.Collection;
-
-public interface CircuitBreakerDefinition {
-    Collection<Class<? extends Throwable>> getFailOn();
-
-    Duration getDelay();
-
-    int getRequestVolumeThreshold();
-
-    double getFailureRatio();
-
-    int getSuccessThreshold();
-
-    double getSuccessRatio();
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerManager.java b/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerManager.java
deleted file mode 100644
index 42028b1..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerManager.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.circuitbreaker;
-
-public interface CircuitBreakerManager {
-    CircuitBreakerBuilder newCircuitBreaker(String name);
-    CircuitBreaker getCircuitBreaker(String name);
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/config/ConfigFacade.java b/safeguard-api/src/main/java/org/apache/safeguard/api/config/ConfigFacade.java
deleted file mode 100644
index a0af320..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/config/ConfigFacade.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.config;
-
-import javax.annotation.Priority;
-import java.time.temporal.ChronoUnit;
-import java.util.Comparator;
-import java.util.ServiceLoader;
-import java.util.SortedSet;
-import java.util.TreeSet;
-
-public abstract class ConfigFacade {
-    private static ConfigFacade INSTANCE;
-
-    public abstract boolean getBoolean(String name, boolean defaultValue);
-    public abstract long getLong(String name, long defaultValue);
-    public abstract int getInt(String name, int defaultValue);
-    public abstract double getDouble(String name, double defaultValue);
-    public abstract ChronoUnit getChronoUnit(String name, ChronoUnit defaultValue);
-    public abstract Class<? extends Throwable>[] getThrowableClasses(String name, Class<? extends Throwable>[] defaultValue);
-
-    public static ConfigFacade getInstance() {
-        if (INSTANCE == null) {
-            INSTANCE = load();
-        }
-        return INSTANCE;
-    }
-
-    public static void setInstance(ConfigFacade configFacade) {
-        INSTANCE = configFacade;
-    }
-
-    private static ConfigFacade load() {
-        ServiceLoader<ConfigFacade> configFacades = ServiceLoader.load(ConfigFacade.class);
-        SortedSet<ConfigFacade> configFacedSet = new TreeSet<>(Comparator.comparingInt(c -> {
-            Priority p = c.getClass().getAnnotation(Priority.class);
-            return p == null ? 1 : p.value();
-        }));
-        for(ConfigFacade facade : configFacades) {
-            configFacedSet.add(facade);
-        }
-        return configFacedSet.first();
-    }
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryBuilder.java b/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryBuilder.java
deleted file mode 100644
index 10228db..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryBuilder.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.retry;
-
-import java.time.Duration;
-
-public interface RetryBuilder {
-
-    RetryBuilder withMaxRetries(int maxRetries);
-    RetryBuilder withDelay(Duration delay);
-    RetryBuilder withMaxDuration(Duration maxDuration);
-    RetryBuilder withJitter(Duration jitter);
-    RetryBuilder withAbortOn(Class<? extends Throwable>... abortOn);
-    RetryBuilder withRetryOn(Class<? extends Throwable>... retryOn);
-
-    RetryDefinition build();
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryDefinition.java b/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryDefinition.java
deleted file mode 100644
index 1383e17..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryDefinition.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.retry;
-
-import java.time.Duration;
-import java.util.Collection;
-
-public interface RetryDefinition {
-
-    int getMaxRetries();
-
-    Duration getDelay();
-
-    Duration getMaxDuration();
-
-    Duration getJitter();
-
-    Collection<Class<? extends Throwable>> getRetryExceptions();
-
-    Collection<Class<? extends Throwable>> getAbortExceptions();
-
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryManager.java b/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryManager.java
deleted file mode 100644
index 054d8d8..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/retry/RetryManager.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.api.retry;
-
-public interface RetryManager {
-    RetryBuilder newRetryDefinition(String name);
-    RetryDefinition getRetryDefinition(String name);
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/exception/AsyncException.java b/safeguard-api/src/main/java/org/apache/safeguard/exception/AsyncException.java
deleted file mode 100644
index f21cf28..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/exception/AsyncException.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.exception;
-
-public class AsyncException extends SafeguardException {
-    public AsyncException(Exception e) {
-        super(e);
-    }
-}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/exception/SafeguardException.java b/safeguard-api/src/main/java/org/apache/safeguard/exception/SafeguardException.java
deleted file mode 100644
index a8991e1..0000000
--- a/safeguard-api/src/main/java/org/apache/safeguard/exception/SafeguardException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.exception;
-
-import org.eclipse.microprofile.faulttolerance.exceptions.FaultToleranceException;
-
-public class SafeguardException extends FaultToleranceException{
-    public SafeguardException() {
-    }
-
-    public SafeguardException(String message) {
-        super(message);
-    }
-
-    public SafeguardException(String message, Throwable cause) {
-        super(message, cause);
-    }
-
-    public SafeguardException(Throwable cause) {
-        super(cause);
-    }
-
-}
diff --git a/safeguard-impl/pom.xml b/safeguard-impl/pom.xml
index f011417..9022b62 100644
--- a/safeguard-impl/pom.xml
+++ b/safeguard-impl/pom.xml
@@ -24,20 +24,26 @@
         <groupId>org.apache.geronimo.safeguard</groupId>
         <version>1.1-SNAPSHOT</version>
     </parent>
-    <name>Apache Safeguard :: Implementation (Failsafe)</name>
+
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>safeguard-impl</artifactId>
+    <name>Apache Safeguard :: Implementation</name>
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.geronimo.safeguard</groupId>
-            <artifactId>safeguard-api</artifactId>
+            <groupId>org.eclipse.microprofile.fault-tolerance</groupId>
+            <artifactId>microprofile-fault-tolerance-api</artifactId>
+            <version>${microprofile-fault-tolerance.version}</version>
+            <scope>provided</scope>
         </dependency>
         <dependency>
-            <groupId>net.jodah</groupId>
-            <artifactId>failsafe</artifactId>
+            <groupId>org.eclipse.microprofile.metrics</groupId>
+            <artifactId>microprofile-metrics-api</artifactId>
+            <version>1.1.1</version>
+            <scope>provided</scope>
         </dependency>
+
         <dependency>
             <groupId>org.jboss.arquillian.testng</groupId>
             <artifactId>arquillian-testng-container</artifactId>
@@ -74,5 +80,34 @@
             <groupId>org.apache.geronimo.config</groupId>
             <artifactId>geronimo-config-impl</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.eclipse.microprofile.fault-tolerance</groupId>
+            <artifactId>microprofile-fault-tolerance-tck</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo</groupId>
+            <artifactId>geronimo-metrics</artifactId>
+            <version>1.0.0</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>3.0.0-M1</version>
+                <configuration>
+                    <dependenciesToScan>
+                        <dependency>org.eclipse.microprofile.fault-tolerance:microprofile-fault-tolerance-tck</dependency>
+                    </dependenciesToScan>
+                    <excludes>
+                        <exclude>org.eclipse.microprofile.fault.tolerance.tck.ConfigTest</exclude>
+                    </excludes>
+                    <trimStackTrace>false</trimStackTrace>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>
\ No newline at end of file
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/FailsafeExecutionManager.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/FailsafeExecutionManager.java
deleted file mode 100644
index db57b3f..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/FailsafeExecutionManager.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl;
-
-import org.apache.safeguard.api.ExecutionManager;
-import org.apache.safeguard.api.bulkhead.BulkheadManager;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerManager;
-import org.apache.safeguard.api.retry.RetryManager;
-import org.apache.safeguard.impl.bulkhead.BulkheadManagerImpl;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreakerManager;
-import org.apache.safeguard.impl.config.MicroprofileAnnotationMapper;
-import org.apache.safeguard.impl.executionPlans.ExecutionPlanFactory;
-import org.apache.safeguard.impl.executorService.DefaultExecutorServiceProvider;
-import org.apache.safeguard.impl.executorService.ExecutorServiceProvider;
-import org.apache.safeguard.impl.retry.FailsafeRetryManager;
-
-import javax.enterprise.inject.Vetoed;
-import javax.interceptor.InvocationContext;
-import java.lang.reflect.Method;
-import java.time.Duration;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
-
-@Vetoed
-public class FailsafeExecutionManager implements ExecutionManager {
-    private final MicroprofileAnnotationMapper mapper;
-    private final BulkheadManager bulkheadManager;
-    private final CircuitBreakerManager circuitBreakerManager;
-    private final RetryManager retryManager;
-    private final ExecutionPlanFactory executionPlanFactory;
-    private final ExecutorServiceProvider executorServiceProvider;
-
-    public FailsafeExecutionManager() {
-        FailsafeCircuitBreakerManager circuitBreakerManager = new FailsafeCircuitBreakerManager();
-        FailsafeRetryManager retryManager = new FailsafeRetryManager();
-        BulkheadManagerImpl bulkheadManager = new BulkheadManagerImpl();
-        this.mapper = MicroprofileAnnotationMapper.getInstance();
-        this.executorServiceProvider = new DefaultExecutorServiceProvider(Executors.newScheduledThreadPool(5));
-        this.executionPlanFactory = new ExecutionPlanFactory(circuitBreakerManager, retryManager, bulkheadManager, mapper,
-                executorServiceProvider);
-        this.circuitBreakerManager = circuitBreakerManager;
-        this.retryManager = retryManager;
-        this.bulkheadManager = bulkheadManager;
-    }
-
-    public FailsafeExecutionManager(MicroprofileAnnotationMapper mapper, BulkheadManagerImpl bulkheadManager,
-                                    FailsafeCircuitBreakerManager circuitBreakerManager, FailsafeRetryManager retryManager,
-                                    ExecutionPlanFactory executionPlanFactory, ExecutorServiceProvider executorServiceProvider) {
-        this.mapper = mapper;
-        this.bulkheadManager = bulkheadManager;
-        this.circuitBreakerManager = circuitBreakerManager;
-        this.retryManager = retryManager;
-        this.executionPlanFactory = executionPlanFactory;
-        this.executorServiceProvider = executorServiceProvider;
-    }
-
-    public Object execute(InvocationContext invocationContext) {
-        Method method = invocationContext.getMethod();
-        return executionPlanFactory.locateExecutionPlan(method).execute(invocationContext::proceed, invocationContext);
-    }
-
-    @Override
-    public <T> T execute(String name, Callable<T> callable) {
-        return executionPlanFactory.locateExecutionPlan(name, null, false).execute(callable, null);
-    }
-
-    public <T> T executeAsync(String name, Callable<T> callable) {
-        return executionPlanFactory.locateExecutionPlan(name, null, true).execute(callable, null);
-    }
-
-    public <T> T executeAsync(String name, Callable<T> callable, Duration timeout) {
-        return executionPlanFactory.locateExecutionPlan(name, timeout, true).execute(callable, null);
-    }
-
-    public ExecutionPlanFactory getExecutionPlanFactory() {
-        return executionPlanFactory;
-    }
-
-    @Override
-    public CircuitBreakerManager getCircuitBreakerManager() {
-        return circuitBreakerManager;
-    }
-
-    @Override
-    public RetryManager getRetryManager() {
-        return retryManager;
-    }
-
-    @Override
-    public BulkheadManager getBulkheadManager() {
-        return bulkheadManager;
-    }
-
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/annotation/AnnotationFinder.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/annotation/AnnotationFinder.java
new file mode 100644
index 0000000..9fe2f28
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/annotation/AnnotationFinder.java
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.safeguard.impl.annotation;
+
+import static java.util.Optional.ofNullable;
+
+import java.lang.annotation.Annotation;
+import java.util.Arrays;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.interceptor.InvocationContext;
+
+@ApplicationScoped
+public class AnnotationFinder {
+    @Inject
+    private BeanManager manager;
+
+    public <T extends Annotation> T findAnnotation(final Class<T> type, final InvocationContext context) {
+        Class<?> target = context.getTarget().getClass();
+        while (target.getName().contains("$$")) {
+            target = target.getSuperclass();
+        }
+        return manager.createAnnotatedType(target).getMethods().stream()
+                .filter(it -> it.getJavaMember().getName().equals(context.getMethod().getName()) &&
+                        Arrays.equals(it.getJavaMember().getParameterTypes(), context.getMethod().getParameterTypes()))
+                .findFirst()
+                .map(m -> m.getAnnotation(type))
+                .orElseGet(() -> ofNullable(context.getMethod().getAnnotation(type))
+                        .orElseGet(() -> context.getTarget().getClass().getAnnotation(type)));
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/asynchronous/AsynchronousInterceptor.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/asynchronous/AsynchronousInterceptor.java
new file mode 100644
index 0000000..fa375f2
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/asynchronous/AsynchronousInterceptor.java
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.safeguard.impl.asynchronous;
+
+import java.util.concurrent.Executor;
+
+import javax.annotation.Priority;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+import org.apache.safeguard.impl.customizable.Safeguard;
+import org.eclipse.microprofile.faulttolerance.Asynchronous;
+
+@Interceptor
+@Asynchronous
+@Priority(Interceptor.Priority.PLATFORM_AFTER + 1)
+public class AsynchronousInterceptor extends BaseAsynchronousInterceptor {
+    @Inject
+    @Safeguard
+    private Executor executor;
+
+    @Override
+    protected Executor getExecutor(final InvocationContext context) {
+        return executor;
+    }
+
+    @AroundInvoke
+    public Object async(final InvocationContext context) throws Exception {
+        return around(context);
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/asynchronous/BaseAsynchronousInterceptor.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/asynchronous/BaseAsynchronousInterceptor.java
new file mode 100644
index 0000000..db68832
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/asynchronous/BaseAsynchronousInterceptor.java
@@ -0,0 +1,129 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.safeguard.impl.asynchronous;
+
+import java.io.Serializable;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.InvocationContext;
+
+import org.eclipse.microprofile.faulttolerance.Asynchronous;
+import org.eclipse.microprofile.faulttolerance.exceptions.FaultToleranceDefinitionException;
+
+public abstract class BaseAsynchronousInterceptor implements Serializable {
+    protected abstract Executor getExecutor(InvocationContext context);
+
+    protected Object around(final InvocationContext context) throws Exception {
+        if (context.getContextData().get(Asynchronous.class.getName()) != null) { // bulkhead or so handling threading
+            return context.proceed();
+        }
+
+        context.getContextData().put(Asynchronous.class.getName(), "true");
+
+        final Class<?> returnType = context.getMethod().getReturnType();
+        if (CompletionStage.class.isAssignableFrom(returnType)) {
+            final CompletableFuture future = new CompletableFuture<>();
+            getExecutor(context).execute(() -> {
+                try {
+                    final Object proceed = context.proceed();
+                    final CompletionStage<?> stage = CompletionStage.class.cast(proceed);
+                    stage.handle((r, e) -> {
+                        if (e != null) {
+                            future.completeExceptionally(e);
+                        } else {
+                            future.complete(r);
+                        }
+                        return null;
+                    });
+                } catch (final Exception e) {
+                    future.completeExceptionally(e);
+                }
+            });
+            return future;
+        }
+        if (Future.class.isAssignableFrom(returnType)) {
+            final CountDownLatch latch = new CountDownLatch(1);
+            final AtomicReference<Future<?>> ref = new AtomicReference<>();
+            getExecutor(context).execute(() -> {
+                final Object proceed;
+                try {
+                    proceed = context.proceed();
+                    ref.set(Future.class.cast(proceed));
+                } catch (final Exception e) {
+                    final CompletableFuture<Object> failingFuture = new CompletableFuture<>();
+                    failingFuture.completeExceptionally(e);
+                    ref.set(failingFuture);
+                } finally {
+                    latch.countDown();
+                }
+            });
+            return new Future() {
+                private void await() {
+                    try {
+                        latch.await();
+                    } catch (final InterruptedException e) {
+                        Thread.currentThread().interrupt();
+                    }
+                }
+
+                @Override
+                public boolean cancel(final boolean mayInterruptIfRunning) {
+                    await();
+                    return ref.get().cancel(mayInterruptIfRunning);
+                }
+
+                @Override
+                public boolean isCancelled() {
+                    await();
+                    return ref.get().isCancelled();
+                }
+
+                @Override
+                public boolean isDone() {
+                    await();
+                    return ref.get().isDone();
+                }
+
+                @Override
+                public Object get() throws InterruptedException, ExecutionException {
+                    await();
+                    return ref.get().get();
+                }
+
+                @Override
+                public Object get(final long timeout, final TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+                    await();
+                    return ref.get().get(timeout, unit);
+                }
+            };
+        }
+        throw new FaultToleranceDefinitionException(
+                "Unsupported return type: " + returnType + " (from: " + context.getMethod() + ")." +
+                        "Should be Future or CompletionStage.");
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadBuilderImpl.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadBuilderImpl.java
deleted file mode 100644
index 825c576..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadBuilderImpl.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.bulkhead;
-
-import org.apache.safeguard.api.bulkhead.BulkheadBuilder;
-import org.apache.safeguard.api.bulkhead.BulkheadDefinition;
-
-public class BulkheadBuilderImpl implements BulkheadBuilder{
-    private final String name;
-    private final BulkheadManagerImpl bulkheadManager;
-    private int maxWaitingExecutions;
-    private int maxConcurrentExecutions;
-    private boolean asynchronous = false;
-
-    BulkheadBuilderImpl(String name, BulkheadManagerImpl bulkheadManager) {
-        this.name = name;
-        this.bulkheadManager = bulkheadManager;
-    }
-
-    @Override
-    public BulkheadBuilder withMaxConcurrency(int maxConcurrency) {
-        this.maxConcurrentExecutions = maxConcurrency;
-        return this;
-    }
-
-    @Override
-    public BulkheadBuilder withMaxWaiting(int overflowCapacity) {
-        this.maxWaitingExecutions = overflowCapacity;
-        return this;
-    }
-
-    @Override
-    public BulkheadBuilder asynchronous() {
-        this.asynchronous = true;
-        return this;
-    }
-
-    @Override
-    public BulkheadDefinition build() {
-        BulkheadDefinitionImpl definition = new BulkheadDefinitionImpl(maxConcurrentExecutions, maxWaitingExecutions, asynchronous);
-        bulkheadManager.register(name, definition);
-        return definition;
-
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadDefinitionImpl.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadDefinitionImpl.java
deleted file mode 100644
index 7c30c13..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadDefinitionImpl.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.bulkhead;
-
-import org.apache.safeguard.api.bulkhead.BulkheadDefinition;
-
-public class BulkheadDefinitionImpl implements BulkheadDefinition{
-    private final int maxConcurrentExecutions;
-    private final int maxWaitingExecutions;
-    private final boolean asynchronous;
-
-    public BulkheadDefinitionImpl(int maxConcurrentExecutions, int maxWaitingExecutions, boolean asynchronous) {
-        this.maxConcurrentExecutions = maxConcurrentExecutions;
-        this.maxWaitingExecutions = maxWaitingExecutions;
-        this.asynchronous = asynchronous;
-    }
-
-    @Override
-    public int getMaxConcurrentExecutions() {
-        return maxConcurrentExecutions;
-    }
-
-    @Override
-    public int getMaxWaitingExecutions() {
-        return maxWaitingExecutions;
-    }
-
-    @Override
-    public boolean isAsynchronous() {
-        return asynchronous;
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadInterceptor.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadInterceptor.java
new file mode 100644
index 0000000..6bdb6f7
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadInterceptor.java
@@ -0,0 +1,131 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.safeguard.impl.bulkhead;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import javax.annotation.Priority;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+import org.apache.safeguard.impl.annotation.AnnotationFinder;
+import org.apache.safeguard.impl.asynchronous.BaseAsynchronousInterceptor;
+import org.eclipse.microprofile.faulttolerance.Asynchronous;
+import org.eclipse.microprofile.faulttolerance.Bulkhead;
+import org.eclipse.microprofile.faulttolerance.exceptions.BulkheadException;
+import org.eclipse.microprofile.faulttolerance.exceptions.FaultToleranceDefinitionException;
+
+@Bulkhead
+@Interceptor
+@Priority(Interceptor.Priority.PLATFORM_AFTER + 5)
+public class BulkheadInterceptor extends BaseAsynchronousInterceptor {
+    private static final String EXECUTOR_KEY = BulkheadInterceptor.class.getName() + ".executor";
+
+    @Inject
+    private Cache cache;
+
+    @AroundInvoke
+    public Object bulkhead(final InvocationContext context) throws Exception {
+        final Map<Method, Model> models = cache.getModels();
+        Model model = models.get(context.getMethod());
+        if (model == null) {
+            model = cache.create(context);
+            final Model existing = models.putIfAbsent(context.getMethod(), model);
+            if (existing != null) {
+                model = existing;
+            }
+        }
+        if (model.useThreads) {
+            context.getContextData().put(EXECUTOR_KEY, model.pool);
+            return around(context);
+        } else {
+            if (!model.semaphore.tryAcquire()) {
+                throw new BulkheadException("No more permission available");
+            }
+            try {
+                return context.proceed();
+            } finally {
+                model.semaphore.release();
+            }
+        }
+    }
+
+    @Override
+    protected Executor getExecutor(final InvocationContext context) {
+        return Executor.class.cast(context.getContextData().get(EXECUTOR_KEY));
+    }
+
+    static class Model {
+        private final int value;
+        private final int waitingQueue;
+        private final boolean useThreads;
+        private final ExecutorService pool;
+        private final Semaphore semaphore;
+
+        private Model(final Bulkhead bulkhead, final boolean useThreads) {
+            this.value = bulkhead.value();
+            if (this.value <= 0) {
+                throw new FaultToleranceDefinitionException("Invalid value in @Bulkhead: " + value);
+            }
+
+            this.waitingQueue = bulkhead.waitingTaskQueue();
+            if (this.waitingQueue <= 0) {
+                throw new FaultToleranceDefinitionException("Invalid value in @Bulkhead: " + value);
+            }
+
+            this.useThreads = useThreads;
+            if (this.useThreads) {
+                this.pool = new ThreadPoolExecutor(value, value, 0L, MILLISECONDS, new ArrayBlockingQueue<>(waitingQueue));
+                this.semaphore = null;
+            } else {
+                this.pool = null;
+                this.semaphore = new Semaphore(value);
+            }
+        }
+    }
+
+    @ApplicationScoped
+    public static class Cache {
+        private final Map<Method, Model> models = new ConcurrentHashMap<>();
+
+        @Inject
+        private AnnotationFinder finder;
+
+        public Map<Method, Model> getModels() {
+            return models;
+        }
+
+        public Model create(final InvocationContext context) {
+            return new Model(finder.findAnnotation(Bulkhead.class, context),
+                    finder.findAnnotation(Asynchronous.class, context) != null);
+        }
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadManagerImpl.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadManagerImpl.java
deleted file mode 100644
index 9794bd7..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/BulkheadManagerImpl.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.bulkhead;
-
-import org.apache.safeguard.api.bulkhead.Bulkhead;
-import org.apache.safeguard.api.bulkhead.BulkheadBuilder;
-import org.apache.safeguard.api.bulkhead.BulkheadManager;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class BulkheadManagerImpl implements BulkheadManager{
-    private Map<String, Bulkhead> bulkheads = new HashMap<>();;
-    @Override
-    public BulkheadBuilder newBulkheadBuilder(String name) {
-        return new BulkheadBuilderImpl(name, this);
-    }
-
-    @Override
-    public Bulkhead getBulkhead(String name) {
-        return bulkheads.get(name);
-    }
-
-    void register(String name, BulkheadDefinitionImpl bulkheadDefinition) {
-        Bulkhead bulkhead;
-        if (bulkheadDefinition.isAsynchronous()) {
-            bulkhead = new ThreadPoolBulkhead(bulkheadDefinition);
-        }
-        else {
-            bulkhead = new SemaphoreBulkhead(bulkheadDefinition);
-        }
-        bulkheads.put(name, bulkhead);
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/SemaphoreBulkhead.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/SemaphoreBulkhead.java
deleted file mode 100644
index 83c940c..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/SemaphoreBulkhead.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.bulkhead;
-
-import org.apache.safeguard.api.bulkhead.Bulkhead;
-import org.apache.safeguard.api.bulkhead.BulkheadDefinition;
-import org.apache.safeguard.exception.SafeguardException;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.Semaphore;
-
-public class SemaphoreBulkhead implements Bulkhead {
-    private final Semaphore semaphore;
-    private final BulkheadDefinition bulkheadDefinition;
-
-    public SemaphoreBulkhead(BulkheadDefinition bulkheadDefinition) {
-        this.semaphore = new Semaphore(bulkheadDefinition.getMaxConcurrentExecutions(), true);
-        this.bulkheadDefinition = bulkheadDefinition;
-    }
-
-    @Override
-    public BulkheadDefinition getBulkheadDefinition() {
-        return this.bulkheadDefinition;
-    }
-
-    @Override
-    public int getCurrentQueueDepth() {
-        return semaphore.getQueueLength();
-    }
-
-    @Override
-    public int getCurrentExecutions() {
-        return bulkheadDefinition.getMaxConcurrentExecutions() - semaphore.availablePermits();
-    }
-
-    @Override
-    public <T> T execute(Callable<T> callable) {
-        try {
-            String name = Thread.currentThread().getName();
-            this.semaphore.acquire();
-            return callable.call();
-        } catch (Exception e) {
-            throw new SafeguardException(e);
-        } finally {
-            this.semaphore.release();
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/ThreadPoolBulkhead.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/ThreadPoolBulkhead.java
deleted file mode 100644
index 1372175..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/bulkhead/ThreadPoolBulkhead.java
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.bulkhead;
-
-import org.apache.safeguard.api.bulkhead.Bulkhead;
-import org.apache.safeguard.api.bulkhead.BulkheadDefinition;
-import org.eclipse.microprofile.faulttolerance.exceptions.BulkheadException;
-
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-public class ThreadPoolBulkhead implements Bulkhead {
-    private final BulkheadDefinition bulkheadDefinition;
-    private final BlockingQueue<Runnable> workQueue;
-    private final ThreadPoolExecutor threadPoolExecutor;
-
-    public ThreadPoolBulkhead(BulkheadDefinition bulkheadDefinition) {
-        this.bulkheadDefinition = bulkheadDefinition;
-        this.workQueue = new LinkedBlockingQueue<>(bulkheadDefinition.getMaxWaitingExecutions());
-        this.threadPoolExecutor = new ThreadPoolExecutor(
-                bulkheadDefinition.getMaxConcurrentExecutions(),
-                bulkheadDefinition.getMaxConcurrentExecutions(),
-                0L, TimeUnit.MILLISECONDS,
-                workQueue,
-                Executors.defaultThreadFactory());
-    }
-
-    @Override
-    public BulkheadDefinition getBulkheadDefinition() {
-        return bulkheadDefinition;
-    }
-
-    @Override
-    public int getCurrentQueueDepth() {
-        return workQueue.size();
-    }
-
-    @Override
-    public int getCurrentExecutions() {
-        return threadPoolExecutor.getActiveCount();
-    }
-
-    @Override
-    public <T> T execute(Callable<T> callable) {
-        try {
-            return (T)new DelegatingFuture<T>((Future<Future<T>>) threadPoolExecutor.submit(callable));
-        } catch (RejectedExecutionException e) {
-            throw new BulkheadException(e);
-        }
-    }
-
-    private class DelegatingFuture<R> implements Future<R>{
-
-        private final Future<Future<R>> child;
-
-        public DelegatingFuture(Future<Future<R>> child) {
-            this.child = child;
-        }
-
-        @Override
-        public boolean cancel(boolean mayInterruptIfRunning) {
-            return child.cancel(mayInterruptIfRunning);
-        }
-
-        @Override
-        public boolean isCancelled() {
-            return child.isCancelled();
-        }
-
-        @Override
-        public boolean isDone() {
-            return child.isDone();
-        }
-
-        @Override
-        public R get() throws InterruptedException, ExecutionException {
-            return child.get().get();
-        }
-
-        @Override
-        public R get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
-            return child.get().get(timeout, unit);
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/FailsafeExecutionManagerProvider.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/FallbackBinding.java
similarity index 66%
rename from safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/FailsafeExecutionManagerProvider.java
rename to safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/FallbackBinding.java
index 37d1cab..dcf579b 100644
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/FailsafeExecutionManagerProvider.java
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/FallbackBinding.java
@@ -16,20 +16,21 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-
 package org.apache.safeguard.impl.cdi;
 
-import org.apache.safeguard.api.ExecutionManager;
-import org.apache.safeguard.impl.FailsafeExecutionManager;
+import javax.enterprise.util.AnnotationLiteral;
 
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.inject.Produces;
+import org.eclipse.microprofile.faulttolerance.Fallback;
+import org.eclipse.microprofile.faulttolerance.FallbackHandler;
 
-@ApplicationScoped
-public class FailsafeExecutionManagerProvider {
-    @Produces
-    @ApplicationScoped
-    public ExecutionManager createExecutionManager() {
-        return new FailsafeExecutionManager();
+public class FallbackBinding extends AnnotationLiteral<Fallback> implements Fallback {
+    @Override
+    public Class<? extends FallbackHandler<?>> value() {
+        return DEFAULT.class;
+    }
+
+    @Override
+    public String fallbackMethod() {
+        return "";
     }
 }
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/MicroProfileValidator.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/MicroProfileValidator.java
deleted file mode 100644
index 714818b..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/MicroProfileValidator.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.cdi;
-
-import org.apache.safeguard.exception.SafeguardException;
-import org.apache.safeguard.impl.util.AnnotationUtil;
-import org.eclipse.microprofile.faulttolerance.Bulkhead;
-import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
-import org.eclipse.microprofile.faulttolerance.ExecutionContext;
-import org.eclipse.microprofile.faulttolerance.Fallback;
-import org.eclipse.microprofile.faulttolerance.Retry;
-import org.eclipse.microprofile.faulttolerance.Timeout;
-
-import javax.enterprise.inject.Vetoed;
-import javax.enterprise.inject.spi.AnnotatedMethod;
-import javax.enterprise.inject.spi.AnnotatedType;
-import java.lang.reflect.Method;
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.function.Consumer;
-
-@Vetoed
-final class MicroProfileValidator {
-    private List<Throwable> capturedThrowables = new ArrayList<>();
-
-    void parse(AnnotatedType<?> annotatedType) {
-        for(AnnotatedMethod<?> method : annotatedType.getMethods()) {
-            Retry retry = AnnotationUtil.getAnnotation(method, annotatedType, Retry.class);
-            if (retry != null) {
-                validateRetry(retry, method);
-            }
-            Bulkhead bulkhead = AnnotationUtil.getAnnotation(method, annotatedType, Bulkhead.class);
-            if (bulkhead != null) {
-                validateBulkhead(bulkhead, method);
-            }
-            Timeout timeout = AnnotationUtil.getAnnotation(method, annotatedType, Timeout.class);
-            if (timeout != null) {
-                validateTimeout(timeout, method);
-            }
-            CircuitBreaker circuitBreaker = AnnotationUtil.getAnnotation(method, annotatedType, CircuitBreaker.class);
-            if (circuitBreaker != null) {
-                validateCircuitBreaker(circuitBreaker, method);
-            }
-            Fallback fallback = AnnotationUtil.getAnnotation(method, annotatedType, Fallback.class);
-            if (fallback != null) {
-                validateFallback(fallback, method, annotatedType);
-            }
-        }
-    }
-
-    private void validateFallback(Fallback fallback, AnnotatedMethod<?> method, AnnotatedType<?> annotatedType) {
-        if(fallback.fallbackMethod().equals("") && fallback.value().equals(Fallback.DEFAULT.class)) {
-            capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method));
-        }
-        else if(!fallback.fallbackMethod().equals("") && !fallback.value().equals(Fallback.DEFAULT.class)) {
-            capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method));
-        }
-        else if(!fallback.fallbackMethod().equals("")) {
-            boolean found = false;
-            for(AnnotatedMethod<?> otherMethod : annotatedType.getMethods()) {
-                if(otherMethod.getJavaMember().getName().equals(fallback.fallbackMethod())) {
-                    found = true;
-                    if(!method.getJavaMember().getReturnType().equals(otherMethod.getJavaMember().getReturnType())) {
-                        capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
-                                " wrong return type"));
-                    } else if(!Arrays.equals(method.getJavaMember().getParameterTypes(), otherMethod.getJavaMember().getParameterTypes())) {
-                        capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
-                                " wrong parameters"));
-                    }
-                }
-            }
-            if (!found) {
-                capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
-                        " fallback method not found"));
-            }
-        }
-        else {
-            try {
-                Method methodHandle = fallback.value().getMethod("handle", ExecutionContext.class);
-                if(!methodHandle.getReturnType().equals(method.getJavaMember().getReturnType())) {
-                    capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
-                            " wrong return type"));
-                }
-            } catch (NoSuchMethodException e) {
-                capturedThrowables.add(new SafeguardException("Invalid Fallback definition on method " + method +
-                        " fallback method not found"));
-            }
-        }
-    }
-
-    private void validateTimeout(Timeout timeout, AnnotatedMethod<?> method) {
-        if(timeout.value() < 0) {
-            capturedThrowables.add(new SafeguardException("Invalid Timeout definition on method " + method));
-        }
-    }
-
-    private void validateCircuitBreaker(CircuitBreaker circuitBreaker, AnnotatedMethod<?> method) {
-        if(circuitBreaker.requestVolumeThreshold() <= 0 || circuitBreaker.delay() < 0 || circuitBreaker.failureRatio() < 0.0
-                || circuitBreaker.failureRatio() > 1.0 || circuitBreaker.successThreshold() <= 0) {
-            capturedThrowables.add(new SafeguardException("Invalid CircuitBreaker definition on method " + method));
-        }
-    }
-
-    private void validateRetry(Retry retry, AnnotatedMethod<?> method) {
-        if(retry.jitter() < 0 || retry.maxDuration() < 0 || retry.delay() < 0 || retry.maxRetries() < 0) {
-            capturedThrowables.add(new SafeguardException("Invalid Retry definition on method " + method));
-        }
-        Duration delay = Duration.of(retry.delay(), retry.delayUnit());
-        Duration maxDuration = Duration.of(retry.maxDuration(), retry.durationUnit());
-        if(maxDuration.compareTo(delay) < 0) {
-            capturedThrowables.add(new SafeguardException("Invalid Retry definition on method " + method));
-        }
-    }
-
-    private void validateBulkhead(Bulkhead bulkhead, AnnotatedMethod<?> method) {
-        if(bulkhead.value() < 0 || bulkhead.waitingTaskQueue() < 0) {
-            capturedThrowables.add(new SafeguardException("Invalid Bulkhead definition on method " + method));
-        }
-    }
-
-    void forThrowable(Consumer<Throwable> consumer) {
-        capturedThrowables.forEach(consumer);
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardExtension.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardExtension.java
index 0bd2e9d..e16294b 100644
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardExtension.java
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardExtension.java
@@ -1,118 +1,72 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
 package org.apache.safeguard.impl.cdi;
 
-import org.apache.safeguard.api.SafeguardEnabled;
-import org.eclipse.microprofile.faulttolerance.Bulkhead;
-import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
-import org.eclipse.microprofile.faulttolerance.Retry;
-import org.eclipse.microprofile.faulttolerance.Timeout;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.concurrent.Executor;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
 import javax.enterprise.event.Observes;
+import javax.enterprise.inject.Any;
+import javax.enterprise.inject.Default;
 import javax.enterprise.inject.spi.AfterBeanDiscovery;
-import javax.enterprise.inject.spi.AnnotatedConstructor;
-import javax.enterprise.inject.spi.AnnotatedField;
-import javax.enterprise.inject.spi.AnnotatedMethod;
-import javax.enterprise.inject.spi.AnnotatedType;
 import javax.enterprise.inject.spi.Extension;
 import javax.enterprise.inject.spi.ProcessAnnotatedType;
-import javax.enterprise.inject.spi.WithAnnotations;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Type;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.Set;
+import javax.enterprise.inject.spi.ProcessBean;
 
-import static org.apache.safeguard.api.SafeguardEnabled.INSTANCE;
+import org.apache.safeguard.impl.config.GeronimoFaultToleranceConfig;
+import org.apache.safeguard.impl.customizable.Safeguard;
+import org.apache.safeguard.impl.fallback.FallbackInterceptor;
 
+// todo: mp.fault.tolerance.interceptor.priority handling
 public class SafeguardExtension implements Extension {
-    private MicroProfileValidator microProfileValidator = new MicroProfileValidator();
-    public <X> void findFaultTolerantBeans(@Observes @WithAnnotations({Retry.class, CircuitBreaker.class, Timeout.class,
-            Bulkhead.class}) ProcessAnnotatedType<X> pat) {
-        if (!pat.getAnnotatedType().isAnnotationPresent(SafeguardEnabled.class)) {
-            pat.setAnnotatedType(new SafeguardAnnotatedTypeWrapper<>(pat.getAnnotatedType()));
-        }
-        microProfileValidator.parse(pat.getAnnotatedType());
+    private boolean foundExecutor;
+
+    void addFallbackInterceptor(@Observes final ProcessAnnotatedType<FallbackInterceptor> processAnnotatedType) {
+        processAnnotatedType.configureAnnotatedType().add(new FallbackBinding());
     }
 
-    public void throwExceptions(@Observes AfterBeanDiscovery afterBeanDiscovery) {
-        microProfileValidator.forThrowable(afterBeanDiscovery::addDefinitionError);
+    void onBean(@Observes final ProcessBean<?> bean) {
+        if (bean.getBean().getQualifiers().stream().anyMatch(it -> it.annotationType() == Safeguard.class)
+            && bean.getBean().getTypes().stream().anyMatch(it -> Executor.class.isAssignableFrom(toClass(it)))) {
+            foundExecutor = true;
+        }
     }
 
-    private static class SafeguardAnnotatedTypeWrapper<X> implements AnnotatedType<X> {
+    void addMissingBeans(@Observes final AfterBeanDiscovery afterBeanDiscovery) {
+        final GeronimoFaultToleranceConfig config = GeronimoFaultToleranceConfig.create();
+        afterBeanDiscovery.addBean()
+                .id("geronimo_safeguard#configuration")
+                .types(GeronimoFaultToleranceConfig.class, Object.class)
+                .beanClass(GeronimoFaultToleranceConfig.class)
+                .qualifiers(Default.Literal.INSTANCE, Any.Literal.INSTANCE)
+                .createWith(c -> config);
 
-        private final AnnotatedType<X> delegate;
-        private final Set<Annotation> annotations;
-
-        private SafeguardAnnotatedTypeWrapper(AnnotatedType<X> delegate) {
-            this.delegate = delegate;
-            Set<Annotation> annotations = delegate.getAnnotations();
-            Set<Annotation> allAnotations = new LinkedHashSet<>();
-            allAnotations.add(INSTANCE);
-            allAnotations.addAll(annotations);
-            this.annotations = allAnotations;
+        if (!foundExecutor) {
+            afterBeanDiscovery.addBean()
+                    .id("geronimo_safeguard#executor")
+                    .types(Executor.class, Object.class)
+                    .beanClass(Executor.class)
+                    .qualifiers(Safeguard.Literal.INSTANCE, Any.Literal.INSTANCE)
+                    .createWith(c -> Executors.newCachedThreadPool())
+                    .destroyWith((e, c) -> ExecutorService.class.cast(e).shutdownNow());
         }
+    }
 
-        @Override
-        public Class<X> getJavaClass() {
-            return delegate.getJavaClass();
-        }
+    public Class<?> toClass(final Type it) {
+        return doToClass(it, 0);
+    }
 
-        @Override
-        public Set<AnnotatedConstructor<X>> getConstructors() {
-            return delegate.getConstructors();
+    private Class<?> doToClass(final Type it, final int iterations) {
+        if (Class.class.isInstance(it)) {
+            return Class.class.cast(it);
         }
-
-        @Override
-        public Set<AnnotatedMethod<? super X>> getMethods() {
-            return delegate.getMethods();
+        if (iterations > 100) { // with generic it happens we can loop here
+            return Object.class;
         }
-
-        @Override
-        public Set<AnnotatedField<? super X>> getFields() {
-            return delegate.getFields();
+        if (ParameterizedType.class.isInstance(it)) {
+            return doToClass(ParameterizedType.class.cast(it).getRawType(), iterations + 1);
         }
-
-        @Override
-        public Type getBaseType() {
-            return delegate.getBaseType();
-        }
-
-        @Override
-        public Set<Type> getTypeClosure() {
-            return delegate.getTypeClosure();
-        }
-
-        @Override
-        public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
-            return SafeguardEnabled.class.equals(annotationType) ? (T) INSTANCE : delegate.getAnnotation(annotationType);
-        }
-
-        @Override
-        public Set<Annotation> getAnnotations() {
-            return Collections.unmodifiableSet(annotations);
-        }
-
-        @Override
-        public boolean isAnnotationPresent(Class<? extends Annotation> annotationType) {
-            return SafeguardEnabled.class.equals(annotationType) || delegate.isAnnotationPresent(annotationType);
-        }
+        return Object.class; // will not match any of our test
     }
 }
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardInterceptor.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardInterceptor.java
deleted file mode 100644
index 1c211b5..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/cdi/SafeguardInterceptor.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.cdi;
-
-import org.apache.safeguard.api.ExecutionManager;
-import org.apache.safeguard.api.SafeguardEnabled;
-import org.apache.safeguard.impl.FailsafeExecutionManager;
-import org.apache.safeguard.impl.util.AnnotationUtil;
-import org.eclipse.microprofile.faulttolerance.Bulkhead;
-import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
-import org.eclipse.microprofile.faulttolerance.Fallback;
-import org.eclipse.microprofile.faulttolerance.Retry;
-import org.eclipse.microprofile.faulttolerance.Timeout;
-
-import javax.annotation.Priority;
-import javax.enterprise.context.Dependent;
-import javax.inject.Inject;
-import javax.interceptor.AroundInvoke;
-import javax.interceptor.Interceptor;
-import javax.interceptor.InvocationContext;
-import java.lang.reflect.Method;
-
-@Interceptor
-@SafeguardEnabled
-@Priority(400)
-@Dependent
-public class SafeguardInterceptor {
-    @Inject
-    private ExecutionManager executionManager;
-
-    @AroundInvoke
-    public Object runSafeguards(InvocationContext invocationContext) throws Exception{
-        if(isMethodSafeguarded(invocationContext.getMethod())) {
-            return executionManager.execute(invocationContext);
-        }
-        else {
-            return invocationContext.proceed();
-        }
-    }
-
-    private boolean isMethodSafeguarded(Method method) {
-        return AnnotationUtil.getAnnotation(method, Retry.class) != null ||
-                AnnotationUtil.getAnnotation(method, CircuitBreaker.class) != null ||
-                AnnotationUtil.getAnnotation(method, Timeout.class) != null ||
-                AnnotationUtil.getAnnotation(method, Fallback.class) != null ||
-                AnnotationUtil.getAnnotation(method, Bulkhead.class) != null;
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/CircuitBreakerInterceptor.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/CircuitBreakerInterceptor.java
new file mode 100644
index 0000000..eecb8e3
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/CircuitBreakerInterceptor.java
@@ -0,0 +1,291 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.safeguard.impl.circuitbreaker;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.EnumMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Stream;
+
+import javax.annotation.Priority;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+import org.apache.safeguard.impl.annotation.AnnotationFinder;
+import org.apache.safeguard.impl.config.ConfigurationMapper;
+import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
+import org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException;
+import org.eclipse.microprofile.faulttolerance.exceptions.FaultToleranceDefinitionException;
+
+@CircuitBreaker
+@Interceptor
+@Priority(Interceptor.Priority.PLATFORM_AFTER + 2)
+public class CircuitBreakerInterceptor implements Serializable {
+    @Inject
+    private Cache cache;
+
+    @AroundInvoke
+    public Object ifNotOpen(final InvocationContext context) throws Exception {
+        final Map<Method, CircuitBreakerImpl> circuitBreakers = cache.getCircuitBreakers();
+        CircuitBreakerImpl circuitBreaker = circuitBreakers.get(context.getMethod());
+        if (circuitBreaker == null) {
+            circuitBreaker = cache.create(context);
+            final CircuitBreakerImpl existing = circuitBreakers.putIfAbsent(context.getMethod(), circuitBreaker);
+            if (existing != null) {
+                circuitBreaker = existing;
+            }
+        }
+        if (!circuitBreaker.checkState()) {
+            throw new CircuitBreakerOpenException(context.getMethod() + " circuit breaker is open");
+        }
+        try {
+            return context.proceed();
+        } catch (final Exception e) {
+            if (circuitBreaker.failOn.length > 0 &&
+                    Stream.of(circuitBreaker.failOn).anyMatch(it -> it.isInstance(e) || it.isInstance(e.getCause()))) {
+                circuitBreaker.incrementAndCheckState(1);
+            }
+            throw e;
+        }
+    }
+
+    private enum State {
+        CLOSED {
+            @Override
+            public State oppositeState() {
+                return OPEN;
+            }
+        },
+
+        OPEN {
+            @Override
+            public State oppositeState() {
+                return CLOSED;
+            }
+        };
+
+        /**
+         * Returns the opposite state to the represented state. This is useful
+         * for flipping the current state.
+         *
+         * @return the opposite state
+         */
+        public abstract State oppositeState();
+    }
+
+    @ApplicationScoped
+    public static class Cache {
+        private final Map<Method, CircuitBreakerImpl> circuitBreakers = new ConcurrentHashMap<>();
+
+        @Inject
+        private AnnotationFinder finder;
+
+        @Inject
+        private ConfigurationMapper mapper;
+
+        public Map<Method, CircuitBreakerImpl> getCircuitBreakers() {
+            return circuitBreakers;
+        }
+
+        public CircuitBreakerImpl create(final InvocationContext context) {
+            final CircuitBreaker definition = mapper.map(
+                    finder.findAnnotation(CircuitBreaker.class, context), context.getMethod(), CircuitBreaker.class);
+            final long delay = definition.delayUnit().getDuration().toNanos() * definition.delay();
+            if (delay < 0) {
+                throw new FaultToleranceDefinitionException("CircuitBreaker delay can't be < 0");
+            }
+
+            final Class<? extends Throwable>[] failOn = definition.failOn();
+
+            final double failureRatio = definition.failureRatio();
+            if (failureRatio < 0) {
+                throw new FaultToleranceDefinitionException("CircuitBreaker failure ratio can't be < 0");
+            }
+
+            final int volumeThreshold = definition.requestVolumeThreshold();
+            if (volumeThreshold < 1) {
+                throw new FaultToleranceDefinitionException("CircuitBreaker volume threshold can't be < 0");
+            }
+
+            final int successThreshold = definition.successThreshold();
+            if (successThreshold < 0) {
+                throw new FaultToleranceDefinitionException("CircuitBreaker success threshold can't be < 0");
+            }
+            return new CircuitBreakerImpl(volumeThreshold, delay, successThreshold, delay, failOn, failureRatio);
+        }
+    }
+
+    // from commons-lang - todo: refine
+    public static class CircuitBreakerImpl {
+        private static final Map<State, StateStrategy> STRATEGY_MAP = createStrategyMap();
+
+        private final AtomicReference<State> state = new AtomicReference<>(State.CLOSED);
+        private final AtomicReference<CheckIntervalData> checkIntervalData;
+        private final int openingThreshold;
+        private final long openingInterval;
+        private final int closingThreshold;
+        private final long closingInterval;
+        private final double failureRatio;
+        private final Class<? extends Throwable>[] failOn;
+
+        private CircuitBreakerImpl(final int openingThreshold, final long openingInterval,
+                                   final int closingThreshold, final long closingInterval,
+                                   final Class<? extends Throwable>[] failOn,
+                                   final double failureRatio) {
+            this.checkIntervalData = new AtomicReference<>(new CheckIntervalData(0, 0));
+            this.openingThreshold = openingThreshold;
+            this.openingInterval = openingInterval;
+            this.closingThreshold = closingThreshold;
+            this.closingInterval = closingInterval;
+            this.failOn = failOn;
+            this.failureRatio = failureRatio;
+        }
+
+        protected static boolean isOpen(final State state) {
+            return state == State.OPEN;
+        }
+
+        protected void changeState(final State newState) {
+            state.compareAndSet(newState.oppositeState(), newState);
+        }
+
+        public boolean checkState() {
+            return performStateCheck(0);
+        }
+
+        public boolean incrementAndCheckState(final Integer increment) {
+            return performStateCheck(increment);
+        }
+
+        private boolean performStateCheck(final int increment) {
+            CheckIntervalData currentData;
+            CheckIntervalData nextData;
+            State currentState;
+            do {
+                final long time = now();
+                currentState = state.get();
+                currentData = checkIntervalData.get();
+                nextData = nextCheckIntervalData(increment, currentData, currentState, time);
+            } while (!updateCheckIntervalData(currentData, nextData));
+            if (stateStrategy(currentState).isStateTransition(this, currentData, nextData)) {
+                currentState = currentState.oppositeState();
+                changeStateAndStartNewCheckInterval(currentState);
+            }
+            return !isOpen(currentState);
+        }
+
+        private boolean updateCheckIntervalData(final CheckIntervalData currentData,
+                                                final CheckIntervalData nextData) {
+            return currentData == nextData
+                    || checkIntervalData.compareAndSet(currentData, nextData);
+        }
+
+        private void changeStateAndStartNewCheckInterval(final State newState) {
+            changeState(newState);
+            checkIntervalData.set(new CheckIntervalData(0, now()));
+        }
+
+        private CheckIntervalData nextCheckIntervalData(final int increment,
+                                                        final CheckIntervalData currentData, final State currentState, final long time) {
+            CheckIntervalData nextData;
+            if (stateStrategy(currentState).isCheckIntervalFinished(this, currentData, time)) {
+                nextData = new CheckIntervalData(increment, time);
+            } else {
+                nextData = currentData.increment(increment);
+            }
+            return nextData;
+        }
+
+        static long now() {
+            return System.nanoTime();
+        }
+
+        private static StateStrategy stateStrategy(final State state) {
+            return STRATEGY_MAP.get(state);
+        }
+
+        private static Map<State, StateStrategy> createStrategyMap() {
+            final Map<State, StateStrategy> map = new EnumMap<>(State.class);
+            map.put(State.CLOSED, new StateStrategyClosed());
+            map.put(State.OPEN, new StateStrategyOpen());
+            return map;
+        }
+
+        private static class CheckIntervalData {
+            private final int eventCount;
+            private final long checkIntervalStart;
+
+            CheckIntervalData(final int count, final long intervalStart) {
+                eventCount = count;
+                checkIntervalStart = intervalStart;
+            }
+
+            private CheckIntervalData increment(final int delta) {
+                return (delta == 0) ? this : new CheckIntervalData(eventCount + delta, checkIntervalStart);
+            }
+        }
+
+        private abstract static class StateStrategy {
+            private boolean isCheckIntervalFinished(final CircuitBreakerImpl breaker,
+                                                   final CheckIntervalData currentData, final long now) {
+                return now - currentData.checkIntervalStart > fetchCheckInterval(breaker);
+            }
+
+            public abstract boolean isStateTransition(CircuitBreakerImpl breaker,
+                                                      CheckIntervalData currentData, CheckIntervalData nextData);
+
+            protected abstract long fetchCheckInterval(CircuitBreakerImpl breaker);
+        }
+
+        private static class StateStrategyClosed extends StateStrategy {
+            @Override
+            public boolean isStateTransition(final CircuitBreakerImpl breaker,
+                                             final CheckIntervalData currentData, final CheckIntervalData nextData) {
+                final long now = now();
+                return nextData.eventCount > breaker.openingThreshold ||
+                        (now != currentData.checkIntervalStart && (currentData.eventCount / (now - currentData.checkIntervalStart)) > breaker.failureRatio);
+            }
+
+            @Override
+            protected long fetchCheckInterval(final CircuitBreakerImpl breaker) {
+                return breaker.openingInterval;
+            }
+        }
+
+        private static class StateStrategyOpen extends StateStrategy {
+            @Override
+            public boolean isStateTransition(final CircuitBreakerImpl breaker,
+                                             final CheckIntervalData currentData, final CheckIntervalData nextData) {
+                return nextData.checkIntervalStart != currentData.checkIntervalStart
+                        && currentData.eventCount < breaker.closingThreshold;
+            }
+
+            @Override
+            protected long fetchCheckInterval(final CircuitBreakerImpl breaker) {
+                return breaker.closingInterval;
+            }
+        }
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreaker.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreaker.java
deleted file mode 100644
index 2a65df5..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreaker.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.circuitbreaker;
-
-import net.jodah.failsafe.CircuitBreaker.State;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreaker;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerState;
-
-public class FailsafeCircuitBreaker implements CircuitBreaker{
-    private final FailsafeCircuitBreakerDefinition circuitBreakerDefinition;
-
-    public FailsafeCircuitBreaker(FailsafeCircuitBreakerDefinition circuitBreakerDefinition) {
-        this.circuitBreakerDefinition = circuitBreakerDefinition;
-    }
-    @Override
-    public FailsafeCircuitBreakerDefinition getDefinition() {
-        return circuitBreakerDefinition;
-    }
-
-    @Override
-    public CircuitBreakerState getState() {
-        State state = circuitBreakerDefinition.getCircuitBreaker().getState();
-        switch(state) {
-            case OPEN:
-                return CircuitBreakerState.OPEN;
-            case CLOSED:
-                return CircuitBreakerState.CLOSED;
-            case HALF_OPEN:
-                return CircuitBreakerState.HALF_OPEN;
-        }
-        throw new RuntimeException("Unknown state "+state);
-    }
-
-    public void transitionState(CircuitBreakerState state) {
-        switch(state) {
-            case OPEN:
-                circuitBreakerDefinition.getCircuitBreaker().open();
-                break;
-            case CLOSED:
-                circuitBreakerDefinition.getCircuitBreaker().close();
-                break;
-            case HALF_OPEN:
-                circuitBreakerDefinition.getCircuitBreaker().halfOpen();
-                break;
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreakerBuilder.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreakerBuilder.java
deleted file mode 100644
index 7fa71f1..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreakerBuilder.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.circuitbreaker;
-
-import net.jodah.failsafe.CircuitBreaker;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerBuilder;
-
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.concurrent.TimeUnit;
-
-import static java.util.Arrays.asList;
-
-public class FailsafeCircuitBreakerBuilder implements CircuitBreakerBuilder {
-    private final String name;
-    private final FailsafeCircuitBreakerManager failsafeCircuitBreakerManager;
-    private final CircuitBreaker circuitBreaker;
-    private final Collection<Class<? extends Throwable>> failOns;
-
-    public FailsafeCircuitBreakerBuilder(String name, FailsafeCircuitBreakerManager failsafeCircuitBreakerManager) {
-        this.name = name;
-        this.failsafeCircuitBreakerManager = failsafeCircuitBreakerManager;
-        this.circuitBreaker = new CircuitBreaker();
-        this.failOns = new ArrayList<>();
-    }
-
-    @Override
-    public FailsafeCircuitBreakerBuilder withDelay(Duration delay) {
-        circuitBreaker.withDelay(delay.toNanos(), TimeUnit.NANOSECONDS);
-        return this;
-    }
-
-    @Override
-    public FailsafeCircuitBreakerBuilder withFailureCount(int failureCount) {
-        circuitBreaker.withFailureThreshold(failureCount);
-        return this;
-    }
-
-    @Override
-    public FailsafeCircuitBreakerBuilder withFailures(int failureCount, int requestCount) {
-        circuitBreaker.withFailureThreshold(failureCount, requestCount);
-        return this;
-    }
-
-    @Override
-    public FailsafeCircuitBreakerBuilder withSuccessCount(int successCount) {
-        circuitBreaker.withSuccessThreshold(successCount);
-        return this;
-    }
-
-    @Override
-    public FailsafeCircuitBreakerBuilder withSuccesses(int successCount, int requestCount) {
-        circuitBreaker.withSuccessThreshold(successCount, requestCount);
-        return this;
-    }
-
-    @Override
-    public FailsafeCircuitBreakerBuilder withFailOn(Class<? extends Throwable>... failOn) {
-        this.failOns.addAll(asList(failOn));
-        circuitBreaker.failOn(failOn);
-        return this;
-    }
-
-    @Override
-    public FailsafeCircuitBreakerDefinition build() {
-        if(failOns.isEmpty()) {
-            throw new IllegalStateException("At least one exception must be registered for failure detection");
-        }
-        FailsafeCircuitBreakerDefinition failsafeCircuitBreakerDefinition = new FailsafeCircuitBreakerDefinition(circuitBreaker, failOns);
-        this.failsafeCircuitBreakerManager.register(name, failsafeCircuitBreakerDefinition);
-        return failsafeCircuitBreakerDefinition;
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreakerDefinition.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreakerDefinition.java
deleted file mode 100644
index 3ba6866..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreakerDefinition.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.circuitbreaker;
-
-import net.jodah.failsafe.CircuitBreaker;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerDefinition;
-
-import java.time.Duration;
-import java.util.Collection;
-
-public class FailsafeCircuitBreakerDefinition implements CircuitBreakerDefinition{
-    private final CircuitBreaker circuitBreaker;
-    private final Collection<Class<? extends Throwable>> failOnExceptions;
-
-    public FailsafeCircuitBreakerDefinition(CircuitBreaker circuitBreaker, Collection<Class<? extends Throwable>> failOnExceptions) {
-        this.circuitBreaker = circuitBreaker;
-        this.failOnExceptions = failOnExceptions;
-    }
-
-    @Override
-    public Collection<Class<? extends Throwable>> getFailOn() {
-        return failOnExceptions;
-    }
-
-    @Override
-    public Duration getDelay() {
-        net.jodah.failsafe.util.Duration delay = circuitBreaker.getDelay();
-        return Duration.ofMillis(delay.toMillis());
-    }
-
-    @Override
-    public int getRequestVolumeThreshold() {
-        return circuitBreaker.getFailureThreshold().denominator;
-    }
-
-    @Override
-    public double getFailureRatio() {
-        return circuitBreaker.getFailureThreshold().ratio;
-    }
-
-    @Override
-    public int getSuccessThreshold() {
-        return circuitBreaker.getSuccessThreshold().denominator;
-    }
-
-    @Override
-    public double getSuccessRatio() {
-        return circuitBreaker.getSuccessThreshold().ratio;
-    }
-
-    public CircuitBreaker getCircuitBreaker() {
-        return circuitBreaker;
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreakerManager.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreakerManager.java
deleted file mode 100644
index 5fcb866..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/circuitbreaker/FailsafeCircuitBreakerManager.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.circuitbreaker;
-
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerManager;
-
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.inject.Vetoed;
-import java.util.HashMap;
-import java.util.Map;
-
-@Vetoed
-public class FailsafeCircuitBreakerManager implements CircuitBreakerManager{
-    private Map<String, FailsafeCircuitBreaker> circuitBreakers = new HashMap<>();;
-
-    @Override
-    public FailsafeCircuitBreakerBuilder newCircuitBreaker(String name) {
-        return new FailsafeCircuitBreakerBuilder(name, this);
-    }
-
-    @Override
-    public FailsafeCircuitBreaker getCircuitBreaker(String name) {
-        return circuitBreakers.get(name);
-    }
-
-    void register(String name, FailsafeCircuitBreakerDefinition failsafeCircuitBreakerDefinition) {
-        this.circuitBreakers.put(name, new FailsafeCircuitBreaker(failsafeCircuitBreakerDefinition));
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/ConfigFacadeFacade.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/ConfigFacadeFacade.java
deleted file mode 100644
index 05b5854..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/ConfigFacadeFacade.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-package org.apache.safeguard.impl.config;
-
-import java.time.temporal.ChronoUnit;
-
-import javax.annotation.Priority;
-
-import org.apache.safeguard.api.config.ConfigFacade;
-
-@Priority(1)
-public class ConfigFacadeFacade extends ConfigFacade {
-    private final ConfigFacade delegate = loadDelegate();
-
-    private ConfigFacade loadDelegate() {
-        final ClassLoader loader = Thread.currentThread().getContextClassLoader();
-        try {
-            final Class<?> loadClass = loader.loadClass("org.eclipse.microprofile.config.ConfigProvider");
-            loadClass.getMethod("getConfig").invoke(null);
-            return new MicroProfileConfigFacade();
-        } catch (final Throwable notHere) {
-            return new DefaultConfigFacade();
-        }
-    }
-
-    @Override
-    public boolean getBoolean(final String name, final boolean defaultValue) {
-        return delegate.getBoolean(name, defaultValue);
-    }
-
-    @Override
-    public long getLong(final String name, final long defaultValue) {
-        return delegate.getLong(name, defaultValue);
-    }
-
-    @Override
-    public int getInt(final String name, final int defaultValue) {
-        return delegate.getInt(name, defaultValue);
-    }
-
-    @Override
-    public double getDouble(final String name, final double defaultValue) {
-        return delegate.getDouble(name, defaultValue);
-    }
-
-    @Override
-    public ChronoUnit getChronoUnit(final String name, final ChronoUnit defaultValue) {
-        return delegate.getChronoUnit(name, defaultValue);
-    }
-
-    @Override
-    public Class<? extends Throwable>[] getThrowableClasses(final String name, final Class<? extends Throwable>[] defaultValue) {
-        return delegate.getThrowableClasses(name, defaultValue);
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/ConfigurationMapper.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/ConfigurationMapper.java
new file mode 100644
index 0000000..bd9ee46
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/ConfigurationMapper.java
@@ -0,0 +1,115 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.safeguard.impl.config;
+
+import static java.util.Optional.ofNullable;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.time.temporal.ChronoUnit;
+import java.util.stream.Stream;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+
+@ApplicationScoped
+public class ConfigurationMapper {
+    @Inject
+    private GeronimoFaultToleranceConfig config;
+
+    public <T extends Annotation> T map(final T instance, final Method sourceMethod, final Class<T> api) {
+        return api.cast(Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
+                new Class<?>[]{api, Enabled.class}, (proxy, method, args) -> {
+            if (method.getDeclaringClass() == Object.class) {
+                return method.invoke(instance, args);
+            }
+            return findConfiguredValue(instance, api, sourceMethod, method, args);
+        }));
+    }
+
+    private <T extends Annotation> Object findConfiguredValue(final T instance, final Class<T> api,
+                                                              final Method sourceMethod,
+                                                              final Method proxyMethod, final Object[] args) {
+        return ofNullable(ofNullable(findDefaultConfiguration(proxyMethod))
+                .orElseGet(() -> ofNullable(findMethodConfiguration(api, sourceMethod, proxyMethod))
+                        .orElseGet(() -> ofNullable(findClassConfiguration(api, sourceMethod, proxyMethod)).orElse(null))))
+                .map(v -> coerce(v, proxyMethod.getReturnType()))
+                .orElseGet(() -> {
+                    try {
+                        return proxyMethod.invoke(instance, args);
+                    } catch (final IllegalAccessException e) {
+                        throw new IllegalStateException(e);
+                    } catch (final InvocationTargetException e) {
+                        throw new IllegalStateException(e.getTargetException());
+                    }
+                });
+    }
+
+    private String findDefaultConfiguration(final Method api) {
+        return config.read(String.format("%s/%s", api.getDeclaringClass().getSimpleName(), api.getName()));
+    }
+
+    private <T extends Annotation> String findClassConfiguration(final Class<T> api, final Method beanMethod, final Method apiMethod) {
+        return config.read(String.format("%s/%s/%s",
+                beanMethod.getDeclaringClass().getName(), api.getSimpleName(), apiMethod.getName()));
+    }
+
+    private <T extends Annotation> String findMethodConfiguration(final Class<T> api, final Method beanMethod, final Method apiMethod) {
+        return config.read(String.format("%s/%s/%s/%s",
+                beanMethod.getDeclaringClass().getName(), beanMethod.getName(), api.getSimpleName(), apiMethod.getName()));
+    }
+
+    private Object coerce(final String raw, final Class<?> expected) {
+        if (expected == long.class || expected == Long.class) {
+            return Long.valueOf(raw);
+        }
+        if (expected == double.class || expected == Double.class) {
+            return Double.valueOf(raw);
+        }
+        if (expected == int.class || expected == Integer.class) {
+            return Integer.valueOf(raw);
+        }
+        if (expected == boolean.class || expected == Boolean.class) {
+            return Boolean.valueOf(raw);
+        }
+        if (expected == ChronoUnit.class) {
+            return ChronoUnit.valueOf(raw);
+        }
+        if (expected == String.class) {
+            return raw;
+        }
+        if (expected == Class[].class) {
+            return Stream.of(raw.split(","))
+                    .map(String::trim)
+                    .filter(it -> !it.isEmpty())
+                    .map(it -> {
+                        try {
+                            return Thread.currentThread().getContextClassLoader().loadClass(it);
+                        } catch (final ClassNotFoundException e) {
+                            throw new IllegalArgumentException(e);
+                        }
+                    })
+                    .toArray();
+        }
+        throw new IllegalArgumentException("Unsupported: " + expected);
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/DefaultConfigFacade.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/DefaultConfigFacade.java
deleted file mode 100644
index 43c4ff5..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/DefaultConfigFacade.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.config;
-
-import java.time.temporal.ChronoUnit;
-import java.util.Optional;
-import java.util.stream.Stream;
-
-import javax.annotation.Priority;
-
-import org.apache.safeguard.api.config.ConfigFacade;
-import org.eclipse.microprofile.config.Config;
-import org.eclipse.microprofile.config.ConfigProvider;
-
-class DefaultConfigFacade extends ConfigFacade {
-    @Override
-    public boolean getBoolean(String name, boolean defaultValue) {
-        return getOptionalValue(name).map(Boolean::parseBoolean).orElse(defaultValue);
-    }
-
-    @Override
-    public long getLong(String name, long defaultValue) {
-        return getOptionalValue(name).map(Long::parseLong).orElse(defaultValue);
-    }
-
-    @Override
-    public int getInt(String name, int defaultValue) {
-        return getOptionalValue(name).map(Integer::parseInt).orElse(defaultValue);
-    }
-
-    @Override
-    public double getDouble(String name, double defaultValue) {
-        return getOptionalValue(name).map(Double::parseDouble).orElse(defaultValue);
-    }
-
-    @Override
-    public ChronoUnit getChronoUnit(String name, ChronoUnit defaultValue) {
-        return getOptionalValue(name).map(ChronoUnit::valueOf).orElse(defaultValue);
-    }
-
-    @Override
-    public Class<? extends Throwable>[] getThrowableClasses(String name, Class<? extends Throwable>[] defaultValue) {
-        return getOptionalValue(name).map(value -> {
-            final ClassLoader loader = Thread.currentThread().getContextClassLoader();
-            return Stream.of(name.split(",")).map(clazz -> {
-                try {
-                    return loader.loadClass(clazz.trim());
-                } catch (final ClassNotFoundException e) {
-                    throw new IllegalArgumentException(e);
-                }
-            }).toArray(Class[]::new);
-        }).orElse(defaultValue);
-    }
-
-    private Optional<String> getOptionalValue(final String name) {
-        return Optional.ofNullable(Optional.ofNullable(System.getenv(name)).orElseGet(() -> System.getProperty(name)));
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/Enabled.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/Enabled.java
new file mode 100644
index 0000000..6472729
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/Enabled.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2017 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.safeguard.impl.config;
+
+public interface Enabled {
+    boolean enabled();
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/FaultToleranceConfigMpConfigImpl.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/FaultToleranceConfigMpConfigImpl.java
new file mode 100644
index 0000000..4fea947
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/FaultToleranceConfigMpConfigImpl.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.safeguard.impl.config;
+
+import javax.enterprise.inject.Vetoed;
+
+import org.eclipse.microprofile.config.Config;
+import org.eclipse.microprofile.config.ConfigProvider;
+
+@Vetoed
+public class FaultToleranceConfigMpConfigImpl implements GeronimoFaultToleranceConfig {
+    private final Config config;
+
+    FaultToleranceConfigMpConfigImpl() {
+        config = ConfigProvider.getConfig();
+    }
+
+    @Override
+    public String read(final String key) {
+        return config.getOptionalValue(key, String.class).orElse(null);
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/GeronimoFaultToleranceConfig.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/GeronimoFaultToleranceConfig.java
new file mode 100644
index 0000000..a525d25
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/GeronimoFaultToleranceConfig.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.safeguard.impl.config;
+
+import static java.util.Comparator.comparing;
+import static java.util.Optional.ofNullable;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.ServiceConfigurationError;
+import java.util.ServiceLoader;
+import java.util.stream.StreamSupport;
+
+import javax.annotation.Priority;
+import javax.enterprise.inject.Vetoed;
+
+@Vetoed
+class DefaultFaultToleranceConfig implements GeronimoFaultToleranceConfig {
+    private final Map<String, String> configuration = new HashMap<>();
+
+    DefaultFaultToleranceConfig() {
+        System.getProperties().stringPropertyNames()
+              .forEach(k -> configuration.put(k, System.getProperty(k)));
+        try (final InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("META-INF/geronimo/microprofile/fault-tolerance.properties")) {
+            if (stream != null) {
+                final Properties properties = new Properties();
+                properties.load(stream);
+                properties.stringPropertyNames().forEach(k -> configuration.put(k, properties.getProperty(k)));
+            }
+        } catch (final IOException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    @Override
+    public String read(final String value) {
+        return configuration.get(value);
+    }
+}
+
+@FunctionalInterface
+public interface GeronimoFaultToleranceConfig {
+
+    String read(String value);
+
+    static GeronimoFaultToleranceConfig create() {
+        try {
+            final Optional<GeronimoFaultToleranceConfig> iterator = StreamSupport.stream(
+                    ServiceLoader.load(GeronimoFaultToleranceConfig.class).spliterator(), false)
+                    .min(comparing(it -> ofNullable(it.getClass().getAnnotation(Priority.class)).map(Priority::value).orElse(0)));
+            if (iterator.isPresent()) {
+                return new WrappedConfig(iterator.orElseThrow(IllegalStateException::new));
+            }
+            return new WrappedConfig(new FaultToleranceConfigMpConfigImpl());
+        } catch (final ServiceConfigurationError | ExceptionInInitializerError | NoClassDefFoundError | Exception e) {
+            // no-op
+        }
+        return new WrappedConfig(new DefaultFaultToleranceConfig());
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/MicroProfileConfigFacade.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/MicroProfileConfigFacade.java
deleted file mode 100644
index 473797a..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/MicroProfileConfigFacade.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.config;
-
-import java.time.temporal.ChronoUnit;
-
-import org.apache.safeguard.api.config.ConfigFacade;
-import org.eclipse.microprofile.config.Config;
-import org.eclipse.microprofile.config.ConfigProvider;
-
-class MicroProfileConfigFacade extends ConfigFacade {
-    private final Config config;
-
-    public MicroProfileConfigFacade() {
-        this(ConfigProvider.getConfig());
-    }
-
-    public MicroProfileConfigFacade(Config config) {
-        this.config = config;
-    }
-
-    @Override
-    public boolean getBoolean(String name, boolean defaultValue) {
-        return config.getOptionalValue(name, Boolean.class).orElse(defaultValue);
-    }
-
-    @Override
-    public long getLong(String name, long defaultValue) {
-        return config.getOptionalValue(name, Long.class).orElse(defaultValue);
-    }
-
-    @Override
-    public int getInt(String name, int defaultValue) {
-        return config.getOptionalValue(name, Integer.class).orElse(defaultValue);
-    }
-
-    @Override
-    public double getDouble(String name, double defaultValue) {
-        return config.getOptionalValue(name, Double.class).orElse(defaultValue);
-    }
-
-    @Override
-    public ChronoUnit getChronoUnit(String name, ChronoUnit defaultValue) {
-        return config.getOptionalValue(name, ChronoUnit.class).orElse(defaultValue);
-    }
-
-    @Override
-    public Class<? extends Throwable>[] getThrowableClasses(String name, Class<? extends Throwable>[] defaultValue) {
-        return config.getOptionalValue(name, Class[].class).orElse(defaultValue);
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/MicroprofileAnnotationMapper.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/MicroprofileAnnotationMapper.java
deleted file mode 100644
index 4387095..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/MicroprofileAnnotationMapper.java
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.config;
-
-import org.apache.safeguard.api.config.ConfigFacade;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreakerBuilder;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreakerDefinition;
-import org.apache.safeguard.impl.retry.FailsafeRetryBuilder;
-import org.apache.safeguard.impl.retry.FailsafeRetryDefinition;
-import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
-import org.eclipse.microprofile.faulttolerance.Retry;
-
-import javax.enterprise.inject.Vetoed;
-import java.lang.reflect.Method;
-import java.time.Duration;
-import java.time.temporal.ChronoUnit;
-import java.util.concurrent.TimeoutException;
-
-@Vetoed
-public class MicroprofileAnnotationMapper {
-    private static MicroprofileAnnotationMapper INSTANCE = new MicroprofileAnnotationMapper();
-    private final ConfigFacade configFacade;
-
-    private MicroprofileAnnotationMapper() {
-        this(ConfigFacade.getInstance());
-    }
-    public MicroprofileAnnotationMapper(ConfigFacade configFacade) {
-        this.configFacade = configFacade;
-    }
-
-    private static final String RETRY_CLASS_FORMAT = "%s/Retry/%s";
-    private static final String RETRY_METHOD_FORMAT = "%s/%s/Retry/%s";
-    private static final String CIRCUIT_BREAKER_CLASS_FORMAT = "%s/CircuitBreaker/%s";
-    private static final String CIRCUIT_BREAKER_METHOD_FORMAT = "%s/%s/CircuitBreaker/%s";
-    public FailsafeRetryDefinition mapRetry(Method method, Retry retry, FailsafeRetryBuilder retryBuilder) {
-        boolean methodLevel = method.isAnnotationPresent(Retry.class);
-        int maxRetries = getRetryValue(method, "maxRetries", methodLevel, retry.maxRetries());
-        Class[] retryOn = getRetryValue(method, "retryOn", methodLevel, retry.retryOn());
-        Class[] abortOn = getRetryValue(method, "abortOn", methodLevel, retry.abortOn());
-
-        long delay = getRetryValue(method, "delay", methodLevel, retry.delay());
-        ChronoUnit delayUnit = getRetryValue(method, "delayUnit", methodLevel, retry.delayUnit());
-
-        long jitter = getRetryValue(method, "jitter", methodLevel, retry.jitter());
-        ChronoUnit jitterUnit = getRetryValue(method, "jitterDelayUnit", methodLevel, retry.jitterDelayUnit());
-
-        long maxDuration = getRetryValue(method, "maxDuration", methodLevel, retry.maxDuration());
-        ChronoUnit maxDurationUnit = getRetryValue(method, "durationUnit", methodLevel, retry.durationUnit());
-
-        retryBuilder.withMaxRetries(maxRetries)
-                .withRetryOn(retryOn)
-                .withRetryOn(TimeoutException.class, org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException.class)
-                .withAbortOn(abortOn);
-        if (delay > 0L) {
-            retryBuilder.withDelay(Duration.of(delay, delayUnit));
-        }
-        if (jitter > 0L) {
-            retryBuilder.withJitter(Duration.of(jitter, jitterUnit));
-        }
-        if (maxDuration > 0L) {
-            retryBuilder.withMaxDuration(Duration.of(maxDuration, maxDurationUnit));
-        }
-        return retryBuilder.build();
-    }
-
-    public FailsafeCircuitBreakerDefinition mapCircuitBreaker(Method method, CircuitBreaker circuitBreaker,
-                                                              FailsafeCircuitBreakerBuilder builder) {
-        boolean methodLevel = method.isAnnotationPresent(CircuitBreaker.class);
-
-        double failureRatio = getCBValue(method, "failureRatio", methodLevel, circuitBreaker.failureRatio());
-        int requestVolumeThreshold = getCBValue(method, "requestVolumeThreshold", methodLevel, circuitBreaker.requestVolumeThreshold());
-        Class[] failOn = getCBValue(method, "failOn", methodLevel, circuitBreaker.failOn());
-        long delay = getCBValue(method, "delay", methodLevel, circuitBreaker.delay());
-        ChronoUnit delayUnit = getCBValue(method, "delayUnit", methodLevel, circuitBreaker.delayUnit());
-        int successThreshold = getCBValue(method, "successThreshold", methodLevel, circuitBreaker.successThreshold());
-
-        int failureCount = (int) (failureRatio * requestVolumeThreshold);
-        FailsafeCircuitBreakerBuilder failsafeCircuitBreakerBuilder = builder
-                .withFailOn(failOn)
-                .withFailOn(TimeoutException.class, org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException.class)
-                .withDelay(Duration.of(delay, delayUnit))
-                .withSuccessCount(successThreshold);
-        if (failureCount > 0) {
-            failsafeCircuitBreakerBuilder.withFailures(failureCount, requestVolumeThreshold);
-        }
-        return failsafeCircuitBreakerBuilder.build();
-    }
-
-    public static MicroprofileAnnotationMapper getInstance() {
-        return INSTANCE;
-    }
-
-    public static void setInstance(MicroprofileAnnotationMapper microprofileAnnotationMapper) {
-        INSTANCE = microprofileAnnotationMapper;
-    }
-
-    // retry config
-    private int getRetryValue(Method method, String name, boolean isMethod, int defaultValue) {
-        String methodKey = String.format(RETRY_METHOD_FORMAT, method.getDeclaringClass().getName(), method.getName(), name);
-        int value = configFacade.getInt(methodKey, defaultValue);
-        if(value != defaultValue || isMethod) {
-            return value;
-        }
-        String classKey = String.format(RETRY_CLASS_FORMAT, method.getDeclaringClass().getName(), name);
-        return configFacade.getInt(classKey, defaultValue);
-    }
-
-    private long getRetryValue(Method method, String name, boolean isMethod, long defaultValue) {
-        String methodKey = String.format(RETRY_METHOD_FORMAT, method.getDeclaringClass().getName(), method.getName(), name);
-        long value = configFacade.getLong(methodKey, defaultValue);
-        if(value != defaultValue || isMethod) {
-            return value;
-        }
-        String classKey = String.format(RETRY_CLASS_FORMAT, method.getDeclaringClass().getName(), name);
-        return configFacade.getLong(classKey, defaultValue);
-    }
-
-    private ChronoUnit getRetryValue(Method method, String name, boolean isMethod, ChronoUnit defaultValue) {
-        String methodKey = String.format(RETRY_METHOD_FORMAT, method.getDeclaringClass().getName(), method.getName(), name);
-        ChronoUnit value = configFacade.getChronoUnit(methodKey, defaultValue);
-        if(value != defaultValue || isMethod) {
-            return value;
-        }
-        String classKey = String.format(RETRY_CLASS_FORMAT, method.getDeclaringClass().getName(), name);
-        return configFacade.getChronoUnit(classKey, defaultValue);
-    }
-
-    private Class[] getRetryValue(Method method, String name, boolean isMethod, Class[] defaultValue) {
-        String methodKey = String.format(RETRY_METHOD_FORMAT, method.getDeclaringClass().getName(), method.getName(), name);
-        Class[] value = configFacade.getThrowableClasses(methodKey, defaultValue);
-        if(value != defaultValue || isMethod) {
-            return value;
-        }
-        String classKey = String.format(RETRY_CLASS_FORMAT, method.getDeclaringClass().getName(), name);
-        return configFacade.getThrowableClasses(classKey, defaultValue);
-    }
-    // circuit breaker config
-    private int getCBValue(Method method, String name, boolean isMethod, int defaultValue) {
-        String methodKey = String.format(CIRCUIT_BREAKER_METHOD_FORMAT, method.getDeclaringClass().getName(), method.getName(), name);
-        int value = configFacade.getInt(methodKey, defaultValue);
-        if(value != defaultValue || isMethod) {
-            return value;
-        }
-        String classKey = String.format(CIRCUIT_BREAKER_CLASS_FORMAT, method.getDeclaringClass().getName(), name);
-        return configFacade.getInt(classKey, defaultValue);
-    }
-
-    private long getCBValue(Method method, String name, boolean isMethod, long defaultValue) {
-        String methodKey = String.format(CIRCUIT_BREAKER_METHOD_FORMAT, method.getDeclaringClass().getName(), method.getName(), name);
-        long value = configFacade.getLong(methodKey, defaultValue);
-        if(value != defaultValue || isMethod) {
-            return value;
-        }
-        String classKey = String.format(CIRCUIT_BREAKER_CLASS_FORMAT, method.getDeclaringClass().getName(), name);
-        return configFacade.getLong(classKey, defaultValue);
-    }
-
-    private double getCBValue(Method method, String name, boolean isMethod, double defaultValue) {
-        String methodKey = String.format(CIRCUIT_BREAKER_METHOD_FORMAT, method.getDeclaringClass().getName(), method.getName(), name);
-        double value = configFacade.getDouble(methodKey, defaultValue);
-        if(value != defaultValue || isMethod) {
-            return value;
-        }
-        String classKey = String.format(CIRCUIT_BREAKER_CLASS_FORMAT, method.getDeclaringClass().getName(), name);
-        return configFacade.getDouble(classKey, defaultValue);
-    }
-
-    private ChronoUnit getCBValue(Method method, String name, boolean isMethod, ChronoUnit defaultValue) {
-        String methodKey = String.format(CIRCUIT_BREAKER_METHOD_FORMAT, method.getDeclaringClass().getName(), method.getName(), name);
-        ChronoUnit value = configFacade.getChronoUnit(methodKey, defaultValue);
-        if(value != defaultValue || isMethod) {
-            return value;
-        }
-        String classKey = String.format(CIRCUIT_BREAKER_CLASS_FORMAT, method.getDeclaringClass().getName(), name);
-        return configFacade.getChronoUnit(classKey, defaultValue);
-    }
-
-    private Class[] getCBValue(Method method, String name, boolean isMethod, Class[] defaultValue) {
-        String methodKey = String.format(CIRCUIT_BREAKER_METHOD_FORMAT, method.getDeclaringClass().getName(), method.getName(), name);
-        Class[] value = configFacade.getThrowableClasses(methodKey, defaultValue);
-        if(value != defaultValue || isMethod) {
-            return value;
-        }
-        String classKey = String.format(CIRCUIT_BREAKER_CLASS_FORMAT, method.getDeclaringClass().getName(), name);
-        return configFacade.getThrowableClasses(classKey, defaultValue);
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/WrappedConfig.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/WrappedConfig.java
new file mode 100644
index 0000000..03bf68b
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/config/WrappedConfig.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.safeguard.impl.config;
+
+import static java.util.Optional.ofNullable;
+
+class WrappedConfig implements GeronimoFaultToleranceConfig {
+    private final GeronimoFaultToleranceConfig delegate;
+
+    WrappedConfig(final GeronimoFaultToleranceConfig config) {
+        this.delegate = config;
+    }
+
+    @Override
+    public String read(final String value) {
+        return ofNullable(delegate.read(value)).orElseGet(() -> delegate.read("geronimo.safeguard." + value));
+    }
+}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/SafeguardEnabled.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/customizable/Safeguard.java
similarity index 60%
rename from safeguard-api/src/main/java/org/apache/safeguard/api/SafeguardEnabled.java
rename to safeguard-impl/src/main/java/org/apache/safeguard/impl/customizable/Safeguard.java
index 4396a9b..931ea35 100644
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/SafeguardEnabled.java
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/customizable/Safeguard.java
@@ -16,21 +16,26 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
+package org.apache.safeguard.impl.customizable;
 
-package org.apache.safeguard.api;
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
-import javax.enterprise.util.AnnotationLiteral;
-import javax.interceptor.InterceptorBinding;
-import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
-@InterceptorBinding
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface SafeguardEnabled {
+import javax.enterprise.util.AnnotationLiteral;
+import javax.inject.Qualifier;
 
-    SafeguardEnabled INSTANCE = new Literal();
-    class Literal extends AnnotationLiteral<SafeguardEnabled> implements SafeguardEnabled {}
+@Qualifier
+@Retention(RUNTIME)
+@Target({METHOD, TYPE, FIELD})
+public @interface Safeguard {
+    final class Literal extends AnnotationLiteral<Safeguard> implements Safeguard {
+        public static final Literal INSTANCE = new Literal();
+
+        private static final long serialVersionUID = 1L;
+    }
 }
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/AsyncFailsafeExecutionPlan.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/AsyncFailsafeExecutionPlan.java
deleted file mode 100644
index 3265448..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/AsyncFailsafeExecutionPlan.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import net.jodah.failsafe.AsyncFailsafe;
-import net.jodah.failsafe.CircuitBreakerOpenException;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreaker;
-import org.apache.safeguard.impl.fallback.FallbackRunner;
-import org.apache.safeguard.impl.retry.FailsafeRetryDefinition;
-
-import javax.interceptor.InvocationContext;
-import java.time.Duration;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ScheduledExecutorService;
-
-public class AsyncFailsafeExecutionPlan extends SyncFailsafeExecutionPlan {
-    private final ScheduledExecutorService executorService;
-    private final Duration timeout;
-
-    public AsyncFailsafeExecutionPlan(FailsafeRetryDefinition retryDefinition,
-                                      FailsafeCircuitBreaker failsafeCircuitBreaker,
-                                      FallbackRunner fallback,
-                                      ScheduledExecutorService executorService,
-                                      Duration timeout) {
-        super(retryDefinition, failsafeCircuitBreaker, fallback);
-        this.executorService = executorService;
-        this.timeout = timeout;
-    }
-
-    @Override
-    public <T> T execute(Callable<T> callable, InvocationContext invocationContext) {
-        AsyncFailsafe<?> asyncFailsafe = getSyncFailsafe(invocationContext).with(executorService);
-        try {
-            if (this.timeout == null) {
-                return asyncFailsafe.get(callable).get();
-            } else {
-                return asyncFailsafe
-                        .get(new TimeoutWrappedCallable<>(callable, executorService, timeout,
-                                super.failsafeCircuitBreaker))
-                        .get();
-            }
-        } catch (CircuitBreakerOpenException e) {
-            throw new org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException(e);
-        } catch (InterruptedException | ExecutionException e) {
-            Throwable cause = e.getCause();
-            if(cause == null) {
-                throw new RuntimeException(e);
-            }
-            if (cause instanceof CircuitBreakerOpenException) {
-                throw new org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException(cause);
-            }
-            else if(cause instanceof RuntimeException) {
-                throw (RuntimeException) cause;
-            }
-            else {
-                throw new RuntimeException(e);
-            }
-        }
-    }
-}
\ No newline at end of file
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/AsyncOnlyExecutionPlan.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/AsyncOnlyExecutionPlan.java
deleted file mode 100644
index e1a708b..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/AsyncOnlyExecutionPlan.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import org.apache.safeguard.exception.AsyncException;
-
-import javax.interceptor.InvocationContext;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-
-class AsyncOnlyExecutionPlan implements ExecutionPlan {
-    private final ExecutorService executorService;
-
-    AsyncOnlyExecutionPlan(ExecutorService executorService) {
-        this.executorService = executorService;
-    }
-
-    @Override
-    public <T> T execute(Callable<T> callable, InvocationContext invocationContext) {
-        Future<T> submitted = executorService.submit(callable);
-        try {
-            return submitted.get();
-        } catch (InterruptedException | ExecutionException e) {
-            throw new AsyncException(e);
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/AsyncTimeoutExecutionPlan.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/AsyncTimeoutExecutionPlan.java
deleted file mode 100644
index 1c3cd50..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/AsyncTimeoutExecutionPlan.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import javax.interceptor.InvocationContext;
-import java.time.Duration;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-
-class AsyncTimeoutExecutionPlan implements ExecutionPlan {
-    private final Duration timeout;
-    private final ExecutorService executorService;
-
-    AsyncTimeoutExecutionPlan(Duration timeout, ExecutorService executorService) {
-        this.timeout = timeout;
-        this.executorService = executorService;
-    }
-
-    @Override
-    public <T> T execute(Callable<T> callable, InvocationContext invocationContext) {
-        Future<T> future = executorService.submit(callable);
-        try {
-            return future.get(timeout.toNanos(), TimeUnit.NANOSECONDS);
-        } catch (ExecutionException e) {
-            if(e.getCause() != null && e.getCause() instanceof RuntimeException) {
-                throw (RuntimeException)e.getCause();
-            }
-            else {
-                throw new RuntimeException(e);
-            }
-        } catch (InterruptedException | TimeoutException e) {
-            throw new org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException(e);
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/BasicExecutionPlan.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/BasicExecutionPlan.java
deleted file mode 100644
index 74881d4..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/BasicExecutionPlan.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import javax.interceptor.InvocationContext;
-import java.util.concurrent.Callable;
-
-public class BasicExecutionPlan implements ExecutionPlan {
-    @Override
-    public <T> T execute(Callable<T> callable, InvocationContext invocationContext) {
-        try {
-            return callable.call();
-        }
-        catch (Exception e) {
-            throw new RuntimeException(e);
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/BulkheadExecutionPlan.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/BulkheadExecutionPlan.java
deleted file mode 100644
index 6553636..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/BulkheadExecutionPlan.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import org.apache.safeguard.api.bulkhead.Bulkhead;
-import org.apache.safeguard.exception.SafeguardException;
-
-import javax.interceptor.InvocationContext;
-import java.util.concurrent.Callable;
-
-public class BulkheadExecutionPlan implements ExecutionPlan{
-    private final Bulkhead bulkhead;
-    private ExecutionPlan child;
-
-    BulkheadExecutionPlan(Bulkhead bulkhead) {
-        this.bulkhead = bulkhead;
-    }
-
-    void setChild(ExecutionPlan child) {
-        this.child = child;
-    }
-
-    @Override
-    public <T> T execute(Callable<T> callable, InvocationContext invocationContext) {
-        if(bulkhead != null && child != null) {
-            return child.execute(() -> bulkhead.execute(callable), invocationContext);
-        } else if(child != null) {
-            return child.execute(callable, invocationContext);
-        } else {
-            throw new SafeguardException("Neither bulkhead nor child specified");
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/ExecutionPlan.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/ExecutionPlan.java
deleted file mode 100644
index 590eaff..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/ExecutionPlan.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import javax.interceptor.InvocationContext;
-import java.util.concurrent.Callable;
-
-public interface ExecutionPlan {
-    <T> T execute(Callable<T> callable, InvocationContext invocationContext);
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/ExecutionPlanFactory.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/ExecutionPlanFactory.java
deleted file mode 100644
index ae5ba7f..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/ExecutionPlanFactory.java
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import org.apache.safeguard.api.bulkhead.Bulkhead;
-import org.apache.safeguard.api.bulkhead.BulkheadBuilder;
-import org.apache.safeguard.api.bulkhead.BulkheadManager;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreaker;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreakerBuilder;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreakerDefinition;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreakerManager;
-import org.apache.safeguard.api.config.ConfigFacade;
-import org.apache.safeguard.impl.config.MicroprofileAnnotationMapper;
-import org.apache.safeguard.impl.executorService.ExecutorServiceProvider;
-import org.apache.safeguard.impl.fallback.FallbackRunner;
-import org.apache.safeguard.impl.retry.FailsafeRetryBuilder;
-import org.apache.safeguard.impl.retry.FailsafeRetryDefinition;
-import org.apache.safeguard.impl.retry.FailsafeRetryManager;
-import org.apache.safeguard.impl.util.NamingUtil;
-import org.eclipse.microprofile.faulttolerance.Asynchronous;
-import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
-import org.eclipse.microprofile.faulttolerance.Fallback;
-import org.eclipse.microprofile.faulttolerance.Retry;
-import org.eclipse.microprofile.faulttolerance.Timeout;
-
-import java.lang.reflect.Method;
-import java.time.Duration;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Executors;
-
-import static org.apache.safeguard.impl.util.AnnotationUtil.getAnnotation;
-
-public class ExecutionPlanFactory {
-    private final FailsafeCircuitBreakerManager circuitBreakerManager;
-    private final FailsafeRetryManager retryManager;
-    private final BulkheadManager bulkheadManager;
-    private final MicroprofileAnnotationMapper microprofileAnnotationMapper;
-    private final ExecutorServiceProvider executorServiceProvider;
-    private ConcurrentMap<String, ExecutionPlan> executionPlanMap = new ConcurrentHashMap<>();
-    private final boolean enableAllMicroProfileFeatures;
-
-    public ExecutionPlanFactory(FailsafeCircuitBreakerManager circuitBreakerManager,
-                                FailsafeRetryManager retryManager,
-                                BulkheadManager bulkheadManager,
-                                MicroprofileAnnotationMapper microprofileAnnotationMapper,
-                                ExecutorServiceProvider executorServiceProvider) {
-        this.circuitBreakerManager = circuitBreakerManager;
-        this.retryManager = retryManager;
-        this.bulkheadManager = bulkheadManager;
-        this.microprofileAnnotationMapper = microprofileAnnotationMapper;
-        this.executorServiceProvider = executorServiceProvider;
-        this.enableAllMicroProfileFeatures = this.enableNonFallbacksForMicroProfile();
-    }
-
-    public ExecutionPlan locateExecutionPlan(String name, Duration timeout, boolean async) {
-        return executionPlanMap.computeIfAbsent(name, key -> {
-            FailsafeCircuitBreaker circuitBreaker = circuitBreakerManager.getCircuitBreaker(key);
-            FailsafeRetryDefinition retryDefinition = retryManager.getRetryDefinition(key);
-            if (circuitBreaker == null && retryDefinition == null) {
-                return null;
-            } else {
-                return new SyncFailsafeExecutionPlan(retryDefinition, circuitBreaker, null);
-            }
-        });
-    }
-
-    public ExecutionPlan locateExecutionPlan(Method method) {
-        final String name = NamingUtil.createName(method);
-        return executionPlanMap.computeIfAbsent(name, key -> {
-            FailsafeCircuitBreaker circuitBreaker = circuitBreakerManager.getCircuitBreaker(name);
-            if (circuitBreaker == null) {
-                circuitBreaker = createCBDefinition(name, method);
-            }
-            FailsafeRetryDefinition retryDefinition = retryManager.getRetryDefinition(name);
-            if (retryDefinition == null) {
-                retryDefinition = createDefinition(name, method);
-            }
-            Bulkhead bulkhead = bulkheadManager.getBulkhead(name);
-            if (bulkhead == null) {
-                bulkhead = createBulkhead(name, method);
-            }
-            boolean isAsync = isAsync(method);
-            Duration timeout = readTimeout(method);
-            FallbackRunner fallbackRunner = this.createFallback(method);
-            if(this.enableAllMicroProfileFeatures) {
-                BulkheadExecutionPlan parent = new BulkheadExecutionPlan(bulkhead);
-                if (circuitBreaker == null && retryDefinition == null && isAsync) {
-                    if (timeout == null) {
-                        parent.setChild(new AsyncOnlyExecutionPlan(executorServiceProvider.getExecutorService()));
-                    } else {
-                        parent.setChild(new AsyncTimeoutExecutionPlan(timeout, executorServiceProvider.getExecutorService()));
-                    }
-                } else if (circuitBreaker == null && retryDefinition == null && timeout != null) {
-                    // then its just timeout
-                    parent.setChild(new AsyncTimeoutExecutionPlan(timeout, executorServiceProvider.getExecutorService()));
-                } else {
-                    if (isAsync || timeout != null) {
-                        parent.setChild(new AsyncFailsafeExecutionPlan(retryDefinition, circuitBreaker, fallbackRunner,
-                                executorServiceProvider.getScheduledExecutorService(), timeout));;
-                    } else if(circuitBreaker == null && retryDefinition == null && fallbackRunner == null) {
-                        parent.setChild(new BasicExecutionPlan());
-                    } else if(circuitBreaker == null && retryDefinition == null) {
-                        parent.setChild(new FallbackOnlyExecutionPlan(fallbackRunner));
-                    } else {
-                        parent.setChild(new SyncFailsafeExecutionPlan(retryDefinition, circuitBreaker, fallbackRunner));
-                    }
-                }
-                return parent;
-            }else {
-                if(fallbackRunner == null) {
-                    return new BasicExecutionPlan();
-                }
-                else {
-                    return new FallbackOnlyExecutionPlan(fallbackRunner);
-                }
-            }
-
-        });
-    }
-
-    private boolean enableNonFallbacksForMicroProfile() {
-        return ConfigFacade.getInstance().getBoolean("MP_Fault_Tolerance_NonFallback_Enabled", true);
-    }
-
-    private FailsafeRetryDefinition createDefinition(String name, Method method) {
-        Retry retry = getAnnotation(method, Retry.class);
-        if (retry == null) {
-            return null;
-        }
-        FailsafeRetryBuilder retryBuilder = retryManager.newRetryDefinition(name);
-        return microprofileAnnotationMapper.mapRetry(method, retry, retryBuilder);
-    }
-
-    private FailsafeCircuitBreaker createCBDefinition(String name, Method method) {
-        CircuitBreaker circuitBreaker = getAnnotation(method, CircuitBreaker.class);
-        if (circuitBreaker == null) {
-            return null;
-        }
-        FailsafeCircuitBreakerBuilder circuitBreakerBuilder = this.circuitBreakerManager.newCircuitBreaker(name);
-        FailsafeCircuitBreakerDefinition circuitBreakerDefinition = microprofileAnnotationMapper.mapCircuitBreaker(method,
-                circuitBreaker, circuitBreakerBuilder);
-        return new FailsafeCircuitBreaker(circuitBreakerDefinition);
-    }
-
-    private Bulkhead createBulkhead(String name, Method method) {
-        org.eclipse.microprofile.faulttolerance.Bulkhead annotation = getAnnotation(method,
-                org.eclipse.microprofile.faulttolerance.Bulkhead.class);
-        if (annotation == null) {
-            return null;
-        }
-        boolean async = getAnnotation(method, Asynchronous.class) != null;
-        BulkheadBuilder bulkheadBuilder = this.bulkheadManager.newBulkheadBuilder(name)
-                .withMaxWaiting(annotation.waitingTaskQueue())
-                .withMaxConcurrency(annotation.value());
-        if(async) {
-            bulkheadBuilder.asynchronous();
-        }
-        bulkheadBuilder.build();
-        return bulkheadManager.getBulkhead(name);
-    }
-
-    private FallbackRunner createFallback(Method method) {
-        Fallback fallback = getAnnotation(method, Fallback.class);
-        if(fallback == null) {
-            return null;
-        }
-        String methodName = "".equals(fallback.fallbackMethod()) ? null : fallback.fallbackMethod();
-        return new FallbackRunner(fallback.value(), methodName);
-    }
-
-    private boolean isAsync(Method method) {
-        return getAnnotation(method, Asynchronous.class) != null &&
-                getAnnotation(method, org.eclipse.microprofile.faulttolerance.Bulkhead.class) == null;
-    }
-
-    private Duration readTimeout(Method method) {
-        Timeout timeout = getAnnotation(method, Timeout.class);
-        if(timeout == null) {
-            return null;
-        }
-        return Duration.of(timeout.value(), timeout.unit());
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/FallbackOnlyExecutionPlan.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/FallbackOnlyExecutionPlan.java
deleted file mode 100644
index 57f56e7..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/FallbackOnlyExecutionPlan.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import org.apache.safeguard.impl.fallback.FallbackRunner;
-
-import javax.interceptor.InvocationContext;
-import java.util.concurrent.Callable;
-
-public class FallbackOnlyExecutionPlan implements ExecutionPlan {
-    private final FallbackRunner fallbackRunner;
-
-    public FallbackOnlyExecutionPlan(FallbackRunner fallbackRunner) {
-        this.fallbackRunner = fallbackRunner;
-    }
-
-    @Override
-    public <T> T execute(Callable<T> callable, InvocationContext invocationContext) {
-        try {
-            return callable.call();
-        }
-        catch (Exception e) {
-            return (T)fallbackRunner.executeFallback(invocationContext);
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/SyncFailsafeExecutionPlan.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/SyncFailsafeExecutionPlan.java
deleted file mode 100644
index 0eec4ad..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/SyncFailsafeExecutionPlan.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import net.jodah.failsafe.CircuitBreakerOpenException;
-import net.jodah.failsafe.Failsafe;
-import net.jodah.failsafe.SyncFailsafe;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreaker;
-import org.apache.safeguard.impl.fallback.FallbackRunner;
-import org.apache.safeguard.impl.retry.FailsafeRetryDefinition;
-
-import javax.interceptor.InvocationContext;
-import java.util.concurrent.Callable;
-
-public class SyncFailsafeExecutionPlan implements ExecutionPlan {
-    protected final FailsafeRetryDefinition retryDefinition;
-    protected final FailsafeCircuitBreaker failsafeCircuitBreaker;
-    private final FallbackRunner fallback;
-
-    SyncFailsafeExecutionPlan(FailsafeRetryDefinition retryDefinition, FailsafeCircuitBreaker failsafeCircuitBreaker, FallbackRunner fallback) {
-        this.retryDefinition = retryDefinition;
-        this.failsafeCircuitBreaker = failsafeCircuitBreaker;
-        this.fallback = fallback;
-        validateConfig();
-    }
-
-    private void validateConfig() {
-        if(retryDefinition == null && failsafeCircuitBreaker == null) {
-            throw new IllegalStateException("For non-async invocations, must have at least one of RetryDefintion or CircuitBreaker defined");
-        }
-    }
-
-    @Override
-    public <T> T execute(Callable<T> callable, InvocationContext invocationContext) {
-        SyncFailsafe<?> syncFailsafe = getSyncFailsafe(invocationContext);
-        try {
-            return syncFailsafe.get(callable);
-        } catch (CircuitBreakerOpenException e) {
-            throw new org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException(e);
-        }
-    }
-
-    SyncFailsafe<?> getSyncFailsafe(InvocationContext invocationContext) {
-        SyncFailsafe<?> syncFailsafe;
-        Callable callable = () -> fallback.executeFallback(invocationContext);
-        if(retryDefinition == null) {
-            syncFailsafe = Failsafe.with(failsafeCircuitBreaker.getDefinition().getCircuitBreaker());
-        }
-        else {
-            if(failsafeCircuitBreaker == null) {
-                syncFailsafe = Failsafe.with(retryDefinition.getRetryPolicy());
-            }
-            else {
-                syncFailsafe = Failsafe.with(retryDefinition.getRetryPolicy())
-                        .with(failsafeCircuitBreaker.getDefinition().getCircuitBreaker());
-            }
-        }
-        if(this.fallback != null) {
-            syncFailsafe = syncFailsafe.withFallback(callable);
-        }
-        return syncFailsafe;
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/TimeoutWrappedCallable.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/TimeoutWrappedCallable.java
deleted file mode 100644
index 31a9fec..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executionPlans/TimeoutWrappedCallable.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerState;
-import org.apache.safeguard.impl.circuitbreaker.FailsafeCircuitBreaker;
-import org.eclipse.microprofile.faulttolerance.exceptions.CircuitBreakerOpenException;
-import org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException;
-
-import java.time.Duration;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
-
-class TimeoutWrappedCallable<T> implements Callable<T> {
-    private final Callable<T> delegate;
-    private final ScheduledExecutorService executorService;
-    private final Duration timeout;
-    private final FailsafeCircuitBreaker failsafeCircuitBreaker;
-    private boolean timedout = false;
-
-    TimeoutWrappedCallable(Callable<T> delegate, ScheduledExecutorService executorService, Duration timeout, FailsafeCircuitBreaker failsafeCircuitBreaker) {
-        this.delegate = delegate;
-        this.executorService = executorService;
-        this.timeout = timeout;
-        this.failsafeCircuitBreaker = failsafeCircuitBreaker;
-    }
-
-    @Override
-    public T call() throws Exception {
-        boolean circuitBreakerOpen = failsafeCircuitBreaker != null && failsafeCircuitBreaker.getState() == CircuitBreakerState.OPEN;
-        if(circuitBreakerOpen) {
-            throw new CircuitBreakerOpenException();
-        }
-        ScheduledFuture<?> scheduledFuture = executorService.schedule(new TimerRunnable(Thread.currentThread(), this),
-                timeout.toNanos(), TimeUnit.NANOSECONDS);
-
-        T result;
-        try {
-            result = delegate.call();
-        } catch (Exception e) {
-            throw e;
-        } finally {
-            scheduledFuture.cancel(true);
-        }
-        if(timedout) {
-            throw new TimeoutException("Execution timed out after " + timeout);
-        }
-        return result;
-    }
-
-    private class TimerRunnable implements Runnable {
-        private final Thread targetThread;
-        private final TimeoutWrappedCallable task;
-
-        private boolean doInterrupt = true;
-        private TimerRunnable(Thread targetThread, TimeoutWrappedCallable task) {
-            this.targetThread = targetThread;
-            this.task = task;
-        }
-
-        @Override
-        public void run() {
-            if(doInterrupt) {
-                task.timedout = true;
-                targetThread.interrupt();
-            }
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executorService/DefaultExecutorServiceProvider.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executorService/DefaultExecutorServiceProvider.java
deleted file mode 100644
index 9d2d615..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executorService/DefaultExecutorServiceProvider.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executorService;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ScheduledExecutorService;
-
-public class DefaultExecutorServiceProvider implements ExecutorServiceProvider {
-    private final ScheduledExecutorService executorService;
-
-    public DefaultExecutorServiceProvider(ScheduledExecutorService executorService) {
-        this.executorService = executorService;
-    }
-
-    @Override
-    public ExecutorService getExecutorService() {
-        return executorService;
-    }
-
-    @Override
-    public ScheduledExecutorService getScheduledExecutorService() {
-        return executorService;
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executorService/ExecutorServiceProvider.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/executorService/ExecutorServiceProvider.java
deleted file mode 100644
index 55b7694..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/executorService/ExecutorServiceProvider.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executorService;
-
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ScheduledExecutorService;
-
-/**
- * Wraps the look up of an ExecutorService to handle SE and EE cases
- */
-public interface ExecutorServiceProvider {
-    ExecutorService getExecutorService();
-    ScheduledExecutorService getScheduledExecutorService();
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/fallback/FallbackInterceptor.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/fallback/FallbackInterceptor.java
new file mode 100644
index 0000000..e3e8a61
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/fallback/FallbackInterceptor.java
@@ -0,0 +1,166 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.safeguard.impl.fallback;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Stream;
+
+import javax.annotation.PreDestroy;
+import javax.annotation.Priority;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.context.spi.CreationalContext;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+import org.apache.safeguard.impl.annotation.AnnotationFinder;
+import org.apache.safeguard.impl.cdi.SafeguardExtension;
+import org.eclipse.microprofile.faulttolerance.ExecutionContext;
+import org.eclipse.microprofile.faulttolerance.Fallback;
+import org.eclipse.microprofile.faulttolerance.FallbackHandler;
+import org.eclipse.microprofile.faulttolerance.exceptions.FaultToleranceDefinitionException;
+
+// @Fallback - added through the extension since the @Target doesnt allow it
+@Interceptor
+@Priority(Interceptor.Priority.PLATFORM_AFTER)
+public class FallbackInterceptor implements Serializable {
+    @Inject
+    private Cache cache;
+
+    @AroundInvoke
+    public Object withFallback(final InvocationContext context) {
+        final Map<Method, FallbackHandler<?>> handlers = cache.getHandlers();
+        FallbackHandler<?> handler = handlers.get(context.getMethod());
+        if (handler == null) {
+            handler = cache.create(context);
+            handlers.putIfAbsent(context.getMethod(), handler);
+        }
+        try {
+            return context.proceed();
+        } catch (final Throwable e) {
+            return handler.handle(new EnrichedExecutionContext() {
+                @Override
+                public Object getTarget() {
+                    return context.getTarget();
+                }
+
+                @Override
+                public Method getMethod() {
+                    return context.getMethod();
+                }
+
+                @Override
+                public Object[] getParameters() {
+                    return context.getParameters();
+                }
+
+                @Override
+                public Throwable getFailure() {
+                    return e;
+                }
+            });
+        }
+    }
+
+    @ApplicationScoped
+    public static class Cache {
+        private final Map<Method, FallbackHandler<?>> handlers = new ConcurrentHashMap<>();
+
+        @Inject
+        private AnnotationFinder finder;
+
+        @Inject
+        private SafeguardExtension extension;
+
+        @Inject
+        private BeanManager beanManager;
+
+        private final Collection<CreationalContext<?>> contexts = new ArrayList<>();
+
+        @PreDestroy
+        private void release() {
+            contexts.forEach(CreationalContext::release);
+        }
+
+        public Map<Method, FallbackHandler<?>> getHandlers() {
+            return handlers;
+        }
+
+        public FallbackHandler<?> create(final InvocationContext context) {
+            final Fallback fallback = finder.findAnnotation(Fallback.class, context);
+            final Class<? extends FallbackHandler<?>> value = fallback.value();
+            final String method = fallback.fallbackMethod();
+            if (!method.isEmpty() && value != Fallback.DEFAULT.class) {
+                throw new FaultToleranceDefinitionException("You can't set a method and handler as fallback on " + context.getMethod());
+            }
+            if (value != Fallback.DEFAULT.class) {
+                Stream.of(value.getInterfaces()).filter(it -> it == FallbackHandler.class)
+                        .findFirst()
+                        .map(it -> ParameterizedType.class.cast(it))
+                        .filter(it -> it.getActualTypeArguments().length == 1)
+                        .map(it -> extension.toClass(context.getMethod().getReturnType()).isAssignableFrom(extension.toClass(it.getActualTypeArguments()[0])))
+                        .orElseThrow(() -> new FaultToleranceDefinitionException("handler does not match method: " + context.getMethod()));
+                final Set<Bean<?>> beans = beanManager.getBeans(value);
+                final Bean<?> handlerBean = beanManager.resolve(beans);
+                final CreationalContext<Object> creationalContext = beanManager.createCreationalContext(null);
+                if (!beanManager.isNormalScope(handlerBean.getScope())) {
+                    contexts.add(creationalContext);
+                }
+                return FallbackHandler.class.cast(beanManager.getReference(handlerBean, FallbackHandler.class, creationalContext));
+            }
+            try {
+                final Method fallbackMethod = context.getTarget().getClass().getMethod(method);
+                if (!extension.toClass(context.getMethod().getReturnType()).isAssignableFrom(extension.toClass(fallbackMethod.getReturnType())) ||
+                        !Arrays.equals(context.getMethod().getParameterTypes(), fallbackMethod.getParameterTypes())) {
+                    throw new FaultToleranceDefinitionException("handler method does not match method: " + context.getMethod());
+                }
+                if (!fallbackMethod.isAccessible()) {
+                    fallbackMethod.setAccessible(true);
+                }
+                return (FallbackHandler<Object>) context1 -> {
+                    try {
+                        return fallbackMethod.invoke(EnrichedExecutionContext.class.cast(context1).getTarget(), context1.getParameters());
+                    } catch (final IllegalAccessException e) {
+                        throw new IllegalStateException(e);
+                    } catch (final InvocationTargetException e) {
+                        throw new IllegalStateException(e.getTargetException());
+                    }
+                };
+            } catch (final NoSuchMethodException e) {
+                throw new FaultToleranceDefinitionException("No method " + method + " in " + context.getTarget());
+            }
+        }
+    }
+
+    private interface EnrichedExecutionContext extends ExecutionContext {
+        Object getTarget();
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/fallback/FallbackRunner.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/fallback/FallbackRunner.java
deleted file mode 100644
index 26e376e..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/fallback/FallbackRunner.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.fallback;
-
-import org.eclipse.microprofile.faulttolerance.ExecutionContext;
-import org.eclipse.microprofile.faulttolerance.FallbackHandler;
-
-import javax.enterprise.inject.spi.CDI;
-import javax.interceptor.InvocationContext;
-import java.lang.reflect.Method;
-import java.lang.reflect.Parameter;
-
-public class FallbackRunner {
-    private final Class<? extends FallbackHandler<?>> handlerClass;
-    private final String method;
-
-    public FallbackRunner(Class<? extends FallbackHandler<?>> handlerClass, String method) {
-        this.handlerClass = handlerClass;
-        this.method = method;
-    }
-
-    public Object executeFallback(InvocationContext invocationContext) {
-        if(method != null) {
-            try {
-                Method method = getMethod(invocationContext.getTarget().getClass());
-                Parameter[] parameters = method.getParameters();
-                if(parameters.length == 0) {
-                    return method.invoke(invocationContext.getTarget());
-                }
-                else {
-                    return method.invoke(invocationContext.getTarget(), invocationContext.getParameters());
-                }
-            } catch (Exception e) {
-                throw new IllegalArgumentException(e);
-            }
-        }
-        else {
-            SafeguardExecutionContext executionContext = new SafeguardExecutionContext(invocationContext.getMethod(),
-                    invocationContext.getParameters());
-            CDI<Object> cdi = CDI.current();
-            FallbackHandler fallbackHandler = null;
-            try {
-                fallbackHandler = cdi.select(handlerClass).get();
-            }
-            catch (Exception e) {
-                try {
-                    fallbackHandler = handlerClass.newInstance();
-                } catch (InstantiationException | IllegalAccessException e1) {
-                    throw new IllegalArgumentException(e);
-                }
-            }
-            return fallbackHandler.handle(executionContext);
-        }
-    }
-
-    private Method getMethod(Class<?> aClass) {
-        for(Method method : aClass.getMethods()) {
-            if(method.getName().equals(this.method)) {
-                return method;
-            }
-        }
-        return null;
-    }
-
-    private static class SafeguardExecutionContext implements ExecutionContext {
-
-        private final Method method;
-        private final Object[] parameters;
-
-        private SafeguardExecutionContext(Method method, Object[] parameters) {
-            this.method = method;
-            this.parameters = parameters;
-        }
-
-        @Override
-        public Method getMethod() {
-            return method;
-        }
-
-        @Override
-        public Object[] getParameters() {
-            return parameters;
-        }
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/metrics/FaultToleranceMetrics.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/metrics/FaultToleranceMetrics.java
new file mode 100644
index 0000000..ec888d3
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/metrics/FaultToleranceMetrics.java
@@ -0,0 +1,62 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.safeguard.impl.metrics;
+
+import static java.util.Comparator.comparing;
+import static java.util.Optional.ofNullable;
+
+import java.util.Optional;
+import java.util.ServiceLoader;
+import java.util.stream.StreamSupport;
+
+import javax.annotation.Priority;
+import javax.enterprise.inject.spi.CDI;
+
+// todo
+public interface FaultToleranceMetrics {
+
+    void inc(String value);
+    void dec(String value);
+
+    static FaultToleranceMetrics create() {
+        try {
+            final Optional<FaultToleranceMetrics> iterator = StreamSupport.stream(
+                    ServiceLoader.load(FaultToleranceMetrics.class).spliterator(), false)
+                    .min(comparing(it -> ofNullable(it.getClass().getAnnotation(Priority.class)).map(Priority::value).orElse(0)));
+            if (iterator.isPresent()) {
+                return iterator.orElseThrow(IllegalStateException::new);
+            }
+            return new MicroprofileMetricsImpl(CDI.current().select(org.eclipse.microprofile.metrics.MetricRegistry.class).get());
+        } catch (final Exception e) {
+            // no-op
+        }
+        return new FaultToleranceMetrics() {
+            @Override
+            public void inc(final String value) {
+                // no-op
+            }
+
+            @Override
+            public void dec(final String value) {
+                // no-op
+            }
+        };
+    }
+}
+
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryBean.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/metrics/MicroprofileMetricsImpl.java
similarity index 61%
rename from safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryBean.java
rename to safeguard-impl/src/main/java/org/apache/safeguard/impl/metrics/MicroprofileMetricsImpl.java
index fcadf03..9bdf74d 100644
--- a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryBean.java
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/metrics/MicroprofileMetricsImpl.java
@@ -16,23 +16,27 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
+package org.apache.safeguard.impl.metrics;
 
-package org.apache.safeguard.retry.test;
+import javax.enterprise.inject.Vetoed;
 
-import java.util.concurrent.Callable;
+import org.eclipse.microprofile.metrics.MetricRegistry;
 
-public class RetryBean implements Callable<String> {
-    private int calls = 0;
-    @Override
-    public String call() throws Exception {
-        calls++;
-        if(calls <= 2) {
-            throw new RuntimeException();
-        }
-        return "called";
+@Vetoed
+class MicroprofileMetricsImpl implements FaultToleranceMetrics {
+    private final MetricRegistry registry;
+
+    MicroprofileMetricsImpl(final MetricRegistry registry) {
+        this.registry = registry;
     }
 
-    public int getCalls() {
-        return calls;
+    @Override
+    public void inc(final String value) {
+        registry.counter(value).inc();
+    }
+
+    @Override
+    public void dec(final String value) {
+        registry.counter(value).dec();
     }
 }
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerState.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/AfterRetryInterceptor.java
similarity index 72%
rename from safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerState.java
rename to safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/AfterRetryInterceptor.java
index 5f63f1e..03d7d13 100644
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerState.java
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/AfterRetryInterceptor.java
@@ -16,11 +16,15 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
+package org.apache.safeguard.impl.retry;
 
-package org.apache.safeguard.api.circuitbreaker;
+import javax.annotation.Priority;
+import javax.interceptor.Interceptor;
 
-public enum CircuitBreakerState {
-    OPEN,
-    CLOSED,
-    HALF_OPEN
+import org.eclipse.microprofile.faulttolerance.Retry;
+
+@Retry
+@Interceptor
+@Priority(Interceptor.Priority.PLATFORM_AFTER + 10)
+public class AfterRetryInterceptor extends BaseRetryInterceptor {
 }
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/BaseRetryInterceptor.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/BaseRetryInterceptor.java
new file mode 100644
index 0000000..dcfc848
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/BaseRetryInterceptor.java
@@ -0,0 +1,129 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.safeguard.impl.retry;
+
+import static java.lang.Math.max;
+import static java.lang.Math.min;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ThreadLocalRandom;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Stream;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.InvocationContext;
+
+import org.apache.safeguard.impl.annotation.AnnotationFinder;
+import org.apache.safeguard.impl.config.ConfigurationMapper;
+import org.eclipse.microprofile.faulttolerance.Retry;
+import org.eclipse.microprofile.faulttolerance.exceptions.FaultToleranceException;
+
+public class BaseRetryInterceptor implements Serializable {
+    @Inject
+    private Cache cache;
+
+    @AroundInvoke
+    public Object retry(final InvocationContext context) throws Exception {
+        final Map<Method, Model> models = cache.getModels();
+        Model model = models.get(context.getMethod());
+        if (model == null) {
+            model = cache.create(context);
+            models.putIfAbsent(context.getMethod(), model);
+        }
+        for (int i = 0; i < model.maxRetries + 1; i++) {
+            try {
+                return context.proceed();
+            } catch (final RuntimeException re) {
+                if (model.abortOn(re)) {
+                    throw new FaultToleranceException(re);
+                }
+                if (model.maxRetries == i) {
+                    throw re;
+                }
+                if (model.retryOn(re)) {
+                    Thread.sleep(model.nextPause());
+                }
+            }
+        }
+        throw new IllegalStateException("Inaccessible but needed to compile");
+    }
+
+    static class Model {
+        private final Class<? extends Throwable>[] abortOn;
+        private final Class<? extends Throwable>[] retryOn;
+        private final long maxDuration;
+        private final int maxRetries;
+        private final long delay;
+        private final long jitter;
+
+        private Model(final Retry retry) {
+            abortOn = retry.abortOn();
+            retryOn = retry.retryOn();
+            maxDuration = retry.delayUnit().getDuration().toNanos() * retry.maxDuration();
+            maxRetries = retry.maxRetries();
+            delay = retry.delayUnit().getDuration().toNanos() * retry.delay();
+            jitter = retry.jitterDelayUnit().getDuration().toNanos() * retry.jitter();
+        }
+
+        private boolean abortOn(final RuntimeException re) {
+            return matches(abortOn, re);
+        }
+
+        private boolean retryOn(final RuntimeException re) {
+            return matches(retryOn, re);
+        }
+
+        private boolean matches(final Class<? extends Throwable>[] list, final RuntimeException re) {
+            return list.length > 0 &&
+                    Stream.of(list).anyMatch(it -> it.isInstance(re) || it.isInstance(re.getCause()));
+        }
+
+        private long nextPause() {
+            final ThreadLocalRandom random = ThreadLocalRandom.current();
+            return TimeUnit.NANOSECONDS.toMillis(
+                    min(maxDuration, max(0, ((random.nextBoolean() ? 1 : -1) * delay) + random.nextLong(jitter))));
+        }
+    }
+
+    @ApplicationScoped
+    public static class Cache {
+        private final Map<Method, Model> models = new ConcurrentHashMap<>();
+
+        @Inject
+        private AnnotationFinder finder;
+
+        @Inject
+        private ConfigurationMapper configurationMapper;
+
+        public Map<Method, Model> getModels() {
+            return models;
+        }
+
+        public Model create(final InvocationContext context) {
+            final Retry retry = finder.findAnnotation(Retry.class, context);
+            final Retry configuredRetry = configurationMapper.map(retry, context.getMethod(), Retry.class);
+            return new Model(configuredRetry);
+        }
+    }
+}
diff --git a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerState.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/BeforeRetryInterceptor.java
similarity index 72%
copy from safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerState.java
copy to safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/BeforeRetryInterceptor.java
index 5f63f1e..257c85b 100644
--- a/safeguard-api/src/main/java/org/apache/safeguard/api/circuitbreaker/CircuitBreakerState.java
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/BeforeRetryInterceptor.java
@@ -16,11 +16,15 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
+package org.apache.safeguard.impl.retry;
 
-package org.apache.safeguard.api.circuitbreaker;
+import javax.annotation.Priority;
+import javax.interceptor.Interceptor;
 
-public enum CircuitBreakerState {
-    OPEN,
-    CLOSED,
-    HALF_OPEN
+import org.eclipse.microprofile.faulttolerance.Retry;
+
+@Retry
+@Interceptor
+@Priority(Interceptor.Priority.PLATFORM_AFTER)
+public class BeforeRetryInterceptor extends BaseRetryInterceptor {
 }
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryBuilder.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryBuilder.java
deleted file mode 100644
index b6fdba7..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryBuilder.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.retry;
-
-import net.jodah.failsafe.RetryPolicy;
-import org.apache.safeguard.api.retry.RetryBuilder;
-
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-public class FailsafeRetryBuilder implements RetryBuilder{
-    private final List<Class<? extends Throwable>> retryOn;
-    private final List<Class<? extends Throwable>> abortOn;
-    private final RetryPolicy retryPolicy;
-    private final String name;
-    private final FailsafeRetryManager failsafeRetryManager;
-
-    FailsafeRetryBuilder(String name, FailsafeRetryManager failsafeRetryManager) {
-        this.name = name;
-        this.failsafeRetryManager = failsafeRetryManager;
-        this.retryOn = new ArrayList<>();
-        this.abortOn = new ArrayList<>();
-        this.retryPolicy = new RetryPolicy();
-    }
-    @Override
-    public FailsafeRetryBuilder withMaxRetries(int maxRetries) {
-        retryPolicy.withMaxRetries(maxRetries);
-        return this;
-    }
-
-    @Override
-    public FailsafeRetryBuilder withDelay(Duration delay) {
-        retryPolicy.withDelay(delay.toNanos(), TimeUnit.NANOSECONDS);
-        return this;
-    }
-
-    @Override
-    public FailsafeRetryBuilder withMaxDuration(Duration maxDuration) {
-        retryPolicy.withMaxDuration(maxDuration.toNanos(), TimeUnit.NANOSECONDS);
-        return this;
-    }
-
-    @Override
-    public FailsafeRetryBuilder withJitter(Duration jitter) {
-        retryPolicy.withJitter(jitter.toNanos(), TimeUnit.NANOSECONDS);
-        return this;
-    }
-
-    @Override
-    public FailsafeRetryBuilder withAbortOn(Class<? extends Throwable>... abortOn) {
-        this.abortOn.addAll(Arrays.asList(abortOn));
-        return this;
-    }
-
-    @Override
-    public FailsafeRetryBuilder withRetryOn(Class<? extends Throwable>... retryOn) {
-        this.retryOn.addAll(Arrays.asList(retryOn));
-        return this;
-    }
-
-    @Override
-    public FailsafeRetryDefinition build() {
-        if(!this.abortOn.isEmpty()) {
-            retryPolicy.abortOn(this.abortOn);
-        }
-        if(!this.retryOn.isEmpty()) {
-            retryPolicy.retryOn(this.retryOn);
-        }
-        FailsafeRetryDefinition definition = new FailsafeRetryDefinition(retryPolicy, retryOn, abortOn);
-        failsafeRetryManager.register(name, definition);
-        return definition;
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryDefinition.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryDefinition.java
deleted file mode 100644
index 916f204..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryDefinition.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.retry;
-
-import net.jodah.failsafe.RetryPolicy;
-import org.apache.safeguard.api.retry.RetryDefinition;
-
-import java.time.Duration;
-import java.util.Collection;
-
-public class FailsafeRetryDefinition implements RetryDefinition{
-    private final RetryPolicy retryPolicy;
-    private final Collection<Class<? extends Throwable>> retryExceptions;
-    private final Collection<Class<? extends Throwable>> abortExceptions;
-
-    FailsafeRetryDefinition(RetryPolicy retryPolicy, Collection<Class<? extends Throwable>> retryExceptions, Collection<Class<? extends Throwable>> abortExceptions) {
-        this.retryPolicy = retryPolicy;
-        this.retryExceptions = retryExceptions;
-        this.abortExceptions = abortExceptions;
-    }
-
-    @Override
-    public int getMaxRetries() {
-        return retryPolicy.getMaxRetries();
-    }
-
-    @Override
-    public Duration getDelay() {
-        net.jodah.failsafe.util.Duration delay = retryPolicy.getDelay();
-        return Duration.ofMillis(delay.toMillis());
-    }
-
-    @Override
-    public Duration getMaxDuration() {
-        net.jodah.failsafe.util.Duration maxDuration = retryPolicy.getMaxDuration();
-        return Duration.ofMillis(maxDuration.toMillis());
-    }
-
-    @Override
-    public Duration getJitter() {
-        net.jodah.failsafe.util.Duration jitter = retryPolicy.getJitter();
-        return Duration.ofMillis(jitter.toMillis());
-    }
-
-    @Override
-    public Collection<Class<? extends Throwable>> getRetryExceptions() {
-        return this.retryExceptions;
-    }
-
-    @Override
-    public Collection<Class<? extends Throwable>> getAbortExceptions() {
-        return abortExceptions;
-    }
-
-    public RetryPolicy getRetryPolicy() {
-        return retryPolicy;
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryManager.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryManager.java
deleted file mode 100644
index 54d41c7..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/retry/FailsafeRetryManager.java
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.retry;
-
-import org.apache.safeguard.api.retry.RetryManager;
-
-import javax.enterprise.inject.Vetoed;
-import java.util.HashMap;
-import java.util.Map;
-
-@Vetoed
-public class FailsafeRetryManager implements RetryManager {
-    private Map<String, FailsafeRetryDefinition> retries = new HashMap<>();
-
-    @Override
-    public FailsafeRetryBuilder newRetryDefinition(String name) {
-        return new FailsafeRetryBuilder(name, this);
-    }
-
-    @Override
-    public FailsafeRetryDefinition getRetryDefinition(String name) {
-        return retries.get(name);
-    }
-
-    void register(String name, FailsafeRetryDefinition failsafeRetryDefinition) {
-        this.retries.put(name, failsafeRetryDefinition);
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/timeout/TimeoutInterceptor.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/timeout/TimeoutInterceptor.java
new file mode 100644
index 0000000..f90f93a
--- /dev/null
+++ b/safeguard-impl/src/main/java/org/apache/safeguard/impl/timeout/TimeoutInterceptor.java
@@ -0,0 +1,112 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.safeguard.impl.timeout;
+
+import static java.util.concurrent.TimeUnit.NANOSECONDS;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeoutException;
+
+import javax.annotation.Priority;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.interceptor.AroundInvoke;
+import javax.interceptor.Interceptor;
+import javax.interceptor.InvocationContext;
+
+import org.apache.safeguard.impl.annotation.AnnotationFinder;
+import org.apache.safeguard.impl.customizable.Safeguard;
+import org.eclipse.microprofile.faulttolerance.Timeout;
+import org.eclipse.microprofile.faulttolerance.exceptions.FaultToleranceDefinitionException;
+
+@Timeout
+@Interceptor
+@Priority(Interceptor.Priority.PLATFORM_AFTER + 20)
+public class TimeoutInterceptor implements Serializable {
+    @Inject
+    private Cache cache;
+
+    @Inject
+    @Safeguard
+    private Executor executor;
+
+    @AroundInvoke
+    public Object withTimeout(final InvocationContext context) throws Exception {
+        final Map<Method, Long> timeouts = cache.getTimeouts();
+        Long duration = timeouts.get(context.getMethod());
+        if (duration == null) {
+            duration = cache.create(context);
+            timeouts.putIfAbsent(context.getMethod(), duration);
+        }
+        final FutureTask<Object> task = new FutureTask<>(context::proceed);
+        executor.execute(task);
+        try {
+            return task.get(duration, NANOSECONDS);
+        } catch (final ExecutionException ee) {
+            cancel(task);
+            throw toCause(ee);
+        } catch (final TimeoutException te) {
+            cancel(task);
+            throw new org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException(te);
+        }
+    }
+
+    private void cancel(final FutureTask<Object> task) {
+        if (!task.isDone()) {
+            task.cancel(true);
+        }
+    }
+
+    private Exception toCause(final Exception te) throws Exception {
+        final Throwable cause = te.getCause();
+        if (Exception.class.isInstance(cause)) {
+            throw Exception.class.cast(cause);
+        }
+        if (Error.class.isInstance(cause)) {
+            throw Error.class.cast(cause);
+        }
+        throw te;
+    }
+
+    @ApplicationScoped
+    public static class Cache {
+        private final Map<Method, Long> timeouts = new ConcurrentHashMap<>();
+
+        @Inject
+        private AnnotationFinder finder;
+
+        public Map<Method, Long> getTimeouts() {
+            return timeouts;
+        }
+
+        public long create(final InvocationContext context) {
+            final Timeout timeout = finder.findAnnotation(Timeout.class, context);
+            if (timeout.value() < 0) {
+                throw new FaultToleranceDefinitionException("Timeout can't be < 0: " + context.getMethod());
+            }
+            return timeout.unit().getDuration().toNanos() * timeout.value();
+        }
+    }
+}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/AnnotationUtil.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/AnnotationUtil.java
deleted file mode 100644
index eb3c478..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/AnnotationUtil.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.util;
-
-import javax.enterprise.inject.spi.AnnotatedMethod;
-import javax.enterprise.inject.spi.AnnotatedType;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-
-public final class AnnotationUtil {
-    private AnnotationUtil() {
-
-    }
-    public static <T extends Annotation> T getAnnotation(Method method, Class<T> clazz) {
-        T annotation = method.getAnnotation(clazz);
-        if (annotation != null) {
-            return annotation;
-        }
-        else {
-            return method.getDeclaringClass().getAnnotation(clazz);
-        }
-    }
-
-    public static <T extends Annotation> T getAnnotation(AnnotatedMethod<?> method,
-                                                         AnnotatedType<?> type,
-                                                         Class<T> clazz) {
-        T annotation = method.getAnnotation(clazz);
-        if(annotation != null) {
-            return annotation;
-        }
-        return type.getAnnotation(clazz);
-    }
-}
diff --git a/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/NamingUtil.java b/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/NamingUtil.java
deleted file mode 100644
index 6773424..0000000
--- a/safeguard-impl/src/main/java/org/apache/safeguard/impl/util/NamingUtil.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.util;
-
-import java.lang.reflect.Method;
-
-public final class NamingUtil {
-    private NamingUtil() {
-
-    }
-
-    public static String createName(Method method) {
-        return method.getDeclaringClass().getCanonicalName()+"."+method.getName();
-    }
-}
diff --git a/safeguard-impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension b/safeguard-impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
index f938390..cb9c016 100644
--- a/safeguard-impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
+++ b/safeguard-impl/src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension
@@ -16,5 +16,4 @@
 #  specific language governing permissions and limitations
 #  under the License.
 #
-
-org.apache.safeguard.impl.cdi.SafeguardExtension
\ No newline at end of file
+org.apache.safeguard.impl.cdi.SafeguardExtension
diff --git a/safeguard-impl/src/main/resources/META-INF/services/org.apache.safeguard.api.config.ConfigFacade b/safeguard-impl/src/main/resources/META-INF/services/org.apache.safeguard.api.config.ConfigFacade
deleted file mode 100644
index 95d5d9b..0000000
--- a/safeguard-impl/src/main/resources/META-INF/services/org.apache.safeguard.api.config.ConfigFacade
+++ /dev/null
@@ -1,20 +0,0 @@
-#
-#  Licensed to the Apache Software Foundation (ASF) under one
-#  or more contributor license agreements.  See the NOTICE file
-#  distributed with this work for additional information
-#  regarding copyright ownership.  The ASF licenses this file
-#  to you under the Apache License, Version 2.0 (the
-#  "License"); you may not use this file except in compliance
-#  with the License.  You may obtain a copy of the License at
-#
-#  http://www.apache.org/licenses/LICENSE-2.0
-#
-#  Unless required by applicable law or agreed to in writing,
-#  software distributed under the License is distributed on an
-#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-#  KIND, either express or implied.  See the License for the
-#  specific language governing permissions and limitations
-#  under the License.
-#
-
-org.apache.safeguard.impl.config.ConfigFacadeFacade
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/SafeguardCDITest.java b/safeguard-impl/src/test/java/org/apache/safeguard/SafeguardCDITest.java
deleted file mode 100644
index 9a9fab6..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/SafeguardCDITest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard;
-
-import org.apache.safeguard.impl.cdi.FailsafeExecutionManagerProvider;
-import org.apache.safeguard.impl.cdi.SafeguardExtension;
-import org.apache.safeguard.impl.cdi.SafeguardInterceptor;
-import org.jboss.arquillian.testng.Arquillian;
-import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.asset.EmptyAsset;
-import org.jboss.shrinkwrap.api.spec.JavaArchive;
-
-import javax.enterprise.inject.spi.Extension;
-
-public abstract class SafeguardCDITest extends Arquillian{
-    public static Archive<?> create(Class<?>...classes) {
-        return ShrinkWrap.create(JavaArchive.class)
-                .addClasses(FailsafeExecutionManagerProvider.class, SafeguardInterceptor.class)
-                .addClasses(classes)
-                .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml")
-                .addAsServiceProviderAndClasses(Extension.class, SafeguardExtension.class);
-    }
-}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/circuitbreaker/test/CDICircuitBean.java b/safeguard-impl/src/test/java/org/apache/safeguard/circuitbreaker/test/CDICircuitBean.java
deleted file mode 100644
index cdbda86..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/circuitbreaker/test/CDICircuitBean.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.circuitbreaker.test;
-
-import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
-
-import javax.enterprise.context.ApplicationScoped;
-
-@ApplicationScoped
-public class CDICircuitBean {
-    @CircuitBreaker(requestVolumeThreshold = 5)
-    public String sayHello() {
-        throw new RuntimeException("I'm failing");
-    }
-}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/circuitbreaker/test/CDICircuitTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/circuitbreaker/test/CDICircuitTest.java
deleted file mode 100644
index f342e0c..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/circuitbreaker/test/CDICircuitTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.circuitbreaker.test;
-
-import org.apache.safeguard.SafeguardCDITest;
-import org.apache.safeguard.api.ExecutionManager;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreaker;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerState;
-import org.apache.safeguard.impl.util.NamingUtil;
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.shrinkwrap.api.Archive;
-import org.testng.annotations.Test;
-
-import javax.inject.Inject;
-import java.lang.reflect.Method;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class CDICircuitTest extends SafeguardCDITest{
-    @Deployment
-    public static Archive<?> createDeployment() {
-        return SafeguardCDITest.create(CDICircuitBean.class);
-    }
-
-    @Inject
-    private CDICircuitBean cdiCircuitBean;
-
-    @Inject
-    private ExecutionManager executionManager;
-
-    @Test
-    public void shouldTriggerCircuitOpen() throws Exception {
-        Method method = CDICircuitBean.class.getMethod("sayHello");
-        String name = NamingUtil.createName(method);
-
-        for(int i = 0;i<5;i++) {
-            try {
-                cdiCircuitBean.sayHello();
-                CircuitBreaker circuitBreaker = executionManager.getCircuitBreakerManager().getCircuitBreaker(name);
-                if (i < 4) {
-                    assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreakerState.CLOSED);
-                }
-                else {
-                    assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreakerState.OPEN);
-                }
-            }
-            catch (Exception e){ }
-        }
-
-        CircuitBreaker circuitBreaker = executionManager.getCircuitBreakerManager().getCircuitBreaker(name);
-        assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreakerState.OPEN);
-    }
-}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/circuitbreaker/test/CircuitTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/circuitbreaker/test/CircuitTest.java
deleted file mode 100644
index 00efc30..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/circuitbreaker/test/CircuitTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.circuitbreaker.test;
-
-import org.apache.safeguard.api.circuitbreaker.CircuitBreaker;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerState;
-import org.apache.safeguard.impl.FailsafeExecutionManager;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class CircuitTest {
-    private FailsafeExecutionManager failsafeExecutionManager;
-    private static final String name = "MY_CIRCUIT_1";
-
-    @BeforeTest
-    public void setupForTest() {
-        failsafeExecutionManager = new FailsafeExecutionManager();
-    }
-
-    @Test
-    public void shouldUseConfiguredCircuit() {
-        int failureCount = 5;
-        failsafeExecutionManager.getCircuitBreakerManager().newCircuitBreaker(name)
-                .withFailureCount(failureCount)
-                .withFailOn(Exception.class)
-                .build();
-        CircuitBreaker circuitBreaker = failsafeExecutionManager.getCircuitBreakerManager().getCircuitBreaker(name);
-        assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreakerState.CLOSED);
-        for(int i = 0; i<failureCount;i++) {
-            try {
-                failsafeExecutionManager.execute(name, () -> {
-                    throw new RuntimeException("Failing");
-                });
-            }
-            catch (Exception e) {}
-        }
-        assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreakerState.OPEN);
-    }
-}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/circuitretry/test/CDIRetryCircuitTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/circuitretry/test/CDIRetryCircuitTest.java
deleted file mode 100644
index e4c6c9c..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/circuitretry/test/CDIRetryCircuitTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.circuitretry.test;
-
-import org.apache.safeguard.SafeguardCDITest;
-import org.apache.safeguard.api.ExecutionManager;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreaker;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerState;
-import org.apache.safeguard.impl.util.NamingUtil;
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.shrinkwrap.api.Archive;
-import org.testng.annotations.Test;
-
-import javax.inject.Inject;
-import java.lang.reflect.Method;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class CDIRetryCircuitTest extends SafeguardCDITest{
-
-    @Deployment
-    public static Archive<?> createDeployment() {
-        return SafeguardCDITest.create(CDISimpleCallable.class);
-    }
-
-    @Inject
-    private CDISimpleCallable simpleCallable;
-
-    @Inject
-    private ExecutionManager executionManager;
-
-    @Test
-    public void shouldExecuteSevenTimes() throws Exception{
-        try {
-            simpleCallable.call();
-        } catch (Exception e) {
-        }
-
-        Method method = CDISimpleCallable.class.getMethod("call");
-        String name = NamingUtil.createName(method);
-        CircuitBreaker circuitBreaker = executionManager.getCircuitBreakerManager().getCircuitBreaker(name);
-
-        assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreakerState.OPEN);
-        assertThat(simpleCallable.getCounter()).isEqualTo(4);
-    }
-
-}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/circuitretry/test/CDISimpleCallable.java b/safeguard-impl/src/test/java/org/apache/safeguard/circuitretry/test/CDISimpleCallable.java
deleted file mode 100644
index 3ba25a2..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/circuitretry/test/CDISimpleCallable.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.circuitretry.test;
-
-import org.eclipse.microprofile.faulttolerance.CircuitBreaker;
-import org.eclipse.microprofile.faulttolerance.Retry;
-
-import javax.enterprise.context.ApplicationScoped;
-import java.util.concurrent.Callable;
-
-@ApplicationScoped
-public class CDISimpleCallable implements Callable<Object> {
-    private int counter = 0;
-
-    @Override
-    @Retry(maxRetries = 7, retryOn = RuntimeException.class)
-    @CircuitBreaker(successThreshold = 2, failureRatio = 0.75, requestVolumeThreshold = 4, delay = 50000)
-    public Object call() throws Exception {
-        counter++;
-        throw new RuntimeException("Invalid state");
-    }
-
-    public int getCounter() {
-        return counter;
-    }
-}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/circuitretry/test/RetryCircuitTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/circuitretry/test/RetryCircuitTest.java
deleted file mode 100644
index 5c6b5e0..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/circuitretry/test/RetryCircuitTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.circuitretry.test;
-
-import org.apache.safeguard.api.circuitbreaker.CircuitBreaker;
-import org.apache.safeguard.api.circuitbreaker.CircuitBreakerState;
-import org.apache.safeguard.impl.FailsafeExecutionManager;
-import org.testng.annotations.Test;
-
-import java.time.Duration;
-import java.util.concurrent.Callable;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class RetryCircuitTest {
-    @Test
-    public void shouldExecuteBothRetryAndCircuitBreaker() {
-        String name = "retryCircuitTest";
-        FailsafeExecutionManager failsafeExecutionManager = new FailsafeExecutionManager();
-        int maxRetries = 7;
-        failsafeExecutionManager.getRetryManager()
-                .newRetryDefinition(name)
-                .withMaxRetries(maxRetries)
-                .withRetryOn(RuntimeException.class).build();
-        failsafeExecutionManager.getCircuitBreakerManager()
-                .newCircuitBreaker(name)
-                .withSuccessCount(2)
-                .withFailures(3, 4)
-                .withDelay(Duration.ofMillis(5000))
-                .withFailOn(RuntimeException.class)
-                .build();
-        CircuitBreaker circuitBreaker = failsafeExecutionManager.getCircuitBreakerManager().getCircuitBreaker(name);
-
-        SimpleCallable simpleCallable = new SimpleCallable();
-        try {
-            failsafeExecutionManager.execute(name, simpleCallable);
-        }catch (RuntimeException e) {
-        }
-        assertThat(circuitBreaker.getState()).isEqualTo(CircuitBreakerState.OPEN);
-        assertThat(simpleCallable.counter).isEqualTo(4);
-    }
-
-    private static class SimpleCallable implements Callable<Object> {
-        private int counter = 0;
-
-        @Override
-        public Object call() throws Exception {
-            counter++;
-            throw new RuntimeException("Invalid state");
-        }
-    }
-}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/ft/tck/ArchiveAppender.java b/safeguard-impl/src/test/java/org/apache/safeguard/ft/tck/ArchiveAppender.java
new file mode 100644
index 0000000..18193d1
--- /dev/null
+++ b/safeguard-impl/src/test/java/org/apache/safeguard/ft/tck/ArchiveAppender.java
@@ -0,0 +1,39 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.apache.safeguard.ft.tck;
+
+import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
+import org.jboss.arquillian.test.spi.TestClass;
+import org.jboss.shrinkwrap.api.Archive;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.EmptyAsset;
+import org.jboss.shrinkwrap.api.spec.JavaArchive;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+
+public class ArchiveAppender implements ApplicationArchiveProcessor {
+
+    @Override
+    public void process(final Archive<?> archive, final TestClass testClass) {
+        archive.as(WebArchive.class)
+                .addAsLibrary(ShrinkWrap.create(JavaArchive.class, "safeguard-impl.jar")
+                        .addPackages(true, "org.apache.safeguard")
+                        .addAsManifestResource(EmptyAsset.INSTANCE, "beans.xml"));
+    }
+}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/ft/tck/IDERunner.java b/safeguard-impl/src/test/java/org/apache/safeguard/ft/tck/IDERunner.java
new file mode 100644
index 0000000..d7d1c0c
--- /dev/null
+++ b/safeguard-impl/src/test/java/org/apache/safeguard/ft/tck/IDERunner.java
@@ -0,0 +1,6 @@
+package org.apache.safeguard.ft.tck;
+
+import org.eclipse.microprofile.fault.tolerance.tck.circuitbreaker.CircuitBreakerConfigOnMethodTest;
+
+public class IDERunner extends CircuitBreakerConfigOnMethodTest {
+}
diff --git a/safeguard-tck-tests/src/test/java/org/apache/safeguard/ft/tck/SafeguardTCKExtension.java b/safeguard-impl/src/test/java/org/apache/safeguard/ft/tck/SafeguardTCKExtension.java
similarity index 94%
rename from safeguard-tck-tests/src/test/java/org/apache/safeguard/ft/tck/SafeguardTCKExtension.java
rename to safeguard-impl/src/test/java/org/apache/safeguard/ft/tck/SafeguardTCKExtension.java
index 6d57660..858dc0e 100644
--- a/safeguard-tck-tests/src/test/java/org/apache/safeguard/ft/tck/SafeguardTCKExtension.java
+++ b/safeguard-impl/src/test/java/org/apache/safeguard/ft/tck/SafeguardTCKExtension.java
@@ -24,7 +24,7 @@
 
 public class SafeguardTCKExtension implements LoadableExtension {
     @Override
-    public void register(ExtensionBuilder extensionBuilder) {
+    public void register(final ExtensionBuilder extensionBuilder) {
         extensionBuilder.service(ApplicationArchiveProcessor.class, ArchiveAppender.class);
     }
 }
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/impl/executionPlans/AsyncOnlyExecutionPlanTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/impl/executionPlans/AsyncOnlyExecutionPlanTest.java
deleted file mode 100644
index 1484f99..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/impl/executionPlans/AsyncOnlyExecutionPlanTest.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import org.testng.annotations.Test;
-
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class AsyncOnlyExecutionPlanTest {
-
-    @Test
-    public void shouldExecuteAsncWithoutTimeout() {
-        AsyncOnlyExecutionPlan asyncOnlyExecutionPlan = new AsyncOnlyExecutionPlan(Executors.newFixedThreadPool(2));
-        MyCallable callable = new MyCallable();
-        asyncOnlyExecutionPlan.execute(callable, null);
-        assertThat(callable.calledThread).isNotEqualTo(Thread.currentThread().getName());
-    }
-
-    private static class MyCallable implements Callable<Object> {
-
-        private String calledThread;
-
-        @Override
-        public Object call() throws Exception {
-            this.calledThread = Thread.currentThread().getName();
-            return "";
-        }
-    }
-
-}
\ No newline at end of file
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/impl/executionPlans/AsyncTimeoutExecutionPlanTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/impl/executionPlans/AsyncTimeoutExecutionPlanTest.java
deleted file mode 100644
index 9bf2ffe..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/impl/executionPlans/AsyncTimeoutExecutionPlanTest.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import org.eclipse.microprofile.faulttolerance.exceptions.TimeoutException;
-import org.testng.annotations.Test;
-
-import java.time.Duration;
-import java.util.concurrent.Callable;
-import java.util.concurrent.Executors;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-public class AsyncTimeoutExecutionPlanTest {
-    @Test
-    public void shouldExecuteSimpleCallable() {
-        AsyncTimeoutExecutionPlan asyncTimeoutExecutionPlan = new AsyncTimeoutExecutionPlan(Duration.ofMillis(1000), Executors.newSingleThreadExecutor());
-        DelayedCaller callable = new DelayedCaller(200);
-
-        asyncTimeoutExecutionPlan.execute(callable, null);
-
-        String myThreadName = Thread.currentThread().getName();
-        assertThat(callable.executedThread).isNotEqualTo(myThreadName);
-    }
-
-    @Test
-    public void shouldThrowTimeoutWhenDelayHit() {
-        AsyncTimeoutExecutionPlan asyncTimeoutExecutionPlan = new AsyncTimeoutExecutionPlan(Duration.ofMillis(100), Executors.newSingleThreadExecutor());
-        DelayedCaller callable = new DelayedCaller(200);
-
-        assertThatThrownBy(() -> asyncTimeoutExecutionPlan.execute(callable, null)).isInstanceOf(TimeoutException.class);
-    }
-
-    private static class DelayedCaller implements Callable<Object> {
-
-        private final long delay;
-        private String executedThread;
-
-        public DelayedCaller(long delay) {
-            this.delay = delay;
-        }
-
-        @Override
-        public Object call() throws Exception {
-            this.executedThread = Thread.currentThread().getName();
-            Thread.sleep(delay);
-            return new Object();
-        }
-    }
-}
\ No newline at end of file
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/impl/executionPlans/SyncFailsafeExecutionPlanTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/impl/executionPlans/SyncFailsafeExecutionPlanTest.java
deleted file mode 100644
index 016cdef..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/impl/executionPlans/SyncFailsafeExecutionPlanTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.impl.executionPlans;
-
-import org.testng.annotations.Test;
-
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-public class SyncFailsafeExecutionPlanTest {
-    @Test
-    public void shouldThrowExceptionWithInvalidConfig() {
-        assertThatThrownBy(() -> new SyncFailsafeExecutionPlan(null, null, null))
-                .isInstanceOf(IllegalStateException.class)
-                .hasMessage("For non-async invocations, must have at least one of RetryDefintion or CircuitBreaker defined");
-    }
-}
\ No newline at end of file
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryBean.java b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryBean.java
deleted file mode 100644
index 3d69ab0..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryBean.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.retry.test;
-
-import org.eclipse.microprofile.faulttolerance.Retry;
-
-import javax.enterprise.context.ApplicationScoped;
-
-@ApplicationScoped
-public class CDIRetryBean {
-    private int calls = 0;
-    @Retry
-    public String doCall() {
-        calls++;
-        if(calls <= 2) {
-            throw new RuntimeException();
-        }
-        return "retried";
-    }
-
-    public int getCalls() {
-        return calls;
-    }
-}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryTest.java
deleted file mode 100644
index 73dbf9e..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/CDIRetryTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.retry.test;
-
-import org.apache.safeguard.SafeguardCDITest;
-import org.apache.safeguard.impl.cdi.FailsafeExecutionManagerProvider;
-import org.apache.safeguard.impl.cdi.SafeguardExtension;
-import org.apache.safeguard.impl.cdi.SafeguardInterceptor;
-import org.jboss.arquillian.container.test.api.Deployment;
-import org.jboss.arquillian.testng.Arquillian;
-import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.asset.EmptyAsset;
-import org.jboss.shrinkwrap.api.spec.JavaArchive;
-import org.testng.annotations.Test;
-
-import javax.enterprise.inject.spi.Extension;
-import javax.inject.Inject;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class CDIRetryTest extends SafeguardCDITest {
-    @Deployment
-    public static Archive<?> create() {
-        return SafeguardCDITest.create(CDIRetryBean.class);
-    }
-
-    @Inject
-    private CDIRetryBean cdiRetryBean;
-
-    @Test
-    public void shouldExecuteThreeTimesWithAnnotations() {
-        cdiRetryBean.doCall();
-
-        assertThat(cdiRetryBean.getCalls()).isEqualTo(3);
-    }
-}
diff --git a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryTest.java b/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryTest.java
deleted file mode 100644
index 094c860..0000000
--- a/safeguard-impl/src/test/java/org/apache/safeguard/retry/test/RetryTest.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.retry.test;
-
-import org.apache.safeguard.impl.FailsafeExecutionManager;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class RetryTest {
-    private FailsafeExecutionManager failsafeExecutionManager;
-    private static final String name = "GUARDED_RETRIES";
-
-    @BeforeTest
-    public void setupForTest() {
-        failsafeExecutionManager = new FailsafeExecutionManager();
-    }
-
-    @Test
-    public void testRetryWithManualBuild() {
-        int expectedCalls = 3;
-        failsafeExecutionManager.getRetryManager().newRetryDefinition(name)
-                .withMaxRetries(expectedCalls)
-                .build();
-        RetryBean retryBean = new RetryBean();
-
-        failsafeExecutionManager.execute(name, retryBean);
-
-        assertThat(retryBean.getCalls()).isEqualTo(expectedCalls);
-    }
-}
diff --git a/safeguard-tck-tests/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension b/safeguard-impl/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
similarity index 99%
rename from safeguard-tck-tests/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
rename to safeguard-impl/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
index 65b7838..577a99e 100644
--- a/safeguard-tck-tests/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
+++ b/safeguard-impl/src/test/resources/META-INF/services/org.jboss.arquillian.core.spi.LoadableExtension
@@ -16,5 +16,4 @@
 #  specific language governing permissions and limitations
 #  under the License.
 #
-
-org.apache.safeguard.ft.tck.SafeguardTCKExtension
\ No newline at end of file
+org.apache.safeguard.ft.tck.SafeguardTCKExtension
diff --git a/safeguard-tck-tests/pom.xml b/safeguard-tck-tests/pom.xml
deleted file mode 100644
index c5e8c42..0000000
--- a/safeguard-tck-tests/pom.xml
+++ /dev/null
@@ -1,79 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  ~  Licensed to the Apache Software Foundation (ASF) under one
-  ~  or more contributor license agreements.  See the NOTICE file
-  ~  distributed with this work for additional information
-  ~  regarding copyright ownership.  The ASF licenses this file
-  ~  to you under the Apache License, Version 2.0 (the
-  ~  "License"); you may not use this file except in compliance
-  ~  with the License.  You may obtain a copy of the License at
-  ~
-  ~  http://www.apache.org/licenses/LICENSE-2.0
-  ~
-  ~  Unless required by applicable law or agreed to in writing,
-  ~  software distributed under the License is distributed on an
-  ~  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-  ~  KIND, either express or implied.  See the License for the
-  ~  specific language governing permissions and limitations
-  ~  under the License.
-  -->
-
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <artifactId>safeguard-parent</artifactId>
-        <groupId>org.apache.geronimo.safeguard</groupId>
-        <version>1.1-SNAPSHOT</version>
-    </parent>
-    <name>Apache Safeguard :: MicroProfile TCK Tests</name>
-    <modelVersion>4.0.0</modelVersion>
-
-    <artifactId>safeguard-tck-tests</artifactId>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.eclipse.microprofile.fault-tolerance</groupId>
-            <artifactId>microprofile-fault-tolerance-tck</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.geronimo.safeguard</groupId>
-            <artifactId>safeguard-impl</artifactId>
-            <version>${project.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcdi_2.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-atinject_1.0_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-annotation_1.3_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-interceptor_1.2_spec</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.geronimo.config</groupId>
-            <artifactId>geronimo-config-impl</artifactId>
-        </dependency>
-    </dependencies>
-    <build>
-        <plugins>
-            <plugin>
-                <artifactId>maven-surefire-plugin</artifactId>
-                <version>2.20</version>
-                <configuration>
-                    <dependenciesToScan>
-                        <dependency>org.eclipse.microprofile.fault-tolerance:microprofile-fault-tolerance-tck</dependency>
-                    </dependenciesToScan>
-                    <excludes>
-                        <exclude>org.eclipse.microprofile.fault.tolerance.tck.ConfigTest</exclude>
-                    </excludes>
-                </configuration>
-            </plugin>
-        </plugins>
-    </build>
-</project>
\ No newline at end of file
diff --git a/safeguard-tck-tests/src/test/java/org/apache/safeguard/ft/tck/ArchiveAppender.java b/safeguard-tck-tests/src/test/java/org/apache/safeguard/ft/tck/ArchiveAppender.java
deleted file mode 100644
index 28b2f58..0000000
--- a/safeguard-tck-tests/src/test/java/org/apache/safeguard/ft/tck/ArchiveAppender.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you under the Apache License, Version 2.0 (the
- *  "License"); you may not use this file except in compliance
- *  with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing,
- *  software distributed under the License is distributed on an
- *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- *  KIND, either express or implied.  See the License for the
- *  specific language governing permissions and limitations
- *  under the License.
- */
-
-package org.apache.safeguard.ft.tck;
-
-import org.apache.safeguard.api.SafeguardEnabled;
-import org.apache.safeguard.api.config.ConfigFacade;
-import org.apache.safeguard.impl.cdi.FailsafeExecutionManagerProvider;
-import org.apache.safeguard.impl.cdi.SafeguardExtension;
-import org.apache.safeguard.impl.cdi.SafeguardInterceptor;
-import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
-import org.jboss.arquillian.test.spi.TestClass;
-import org.jboss.shrinkwrap.api.Archive;
-import org.jboss.shrinkwrap.api.ShrinkWrap;
-import org.jboss.shrinkwrap.api.asset.StringAsset;
-import org.jboss.shrinkwrap.api.spec.JavaArchive;
-import org.jboss.shrinkwrap.api.spec.WebArchive;
-
-import javax.enterprise.inject.spi.Extension;
-
-public class ArchiveAppender implements ApplicationArchiveProcessor {
-    private static final StringAsset BEANS_XML = new StringAsset("<beans version=\"1.1\" bean-discovery-mode=\"all\"/>");
-
-    @Override
-    public void process(Archive<?> archive, TestClass testClass) {
-        ConfigFacade.setInstance(null);
-        JavaArchive jar = ShrinkWrap.create(JavaArchive.class, "safeguard.jar")
-                .addClasses(SafeguardEnabled.class, SafeguardExtension.class, FailsafeExecutionManagerProvider.class, SafeguardInterceptor.class)
-                .addAsServiceProvider(Extension.class, SafeguardExtension.class)
-                .addAsManifestResource(BEANS_XML, "beans.xml");
-        archive.as(WebArchive.class).addAsLibrary(jar);
-    }
-}