diff --git a/consul/deployment/src/main/java/io/quarkus/consul/config/ConsulConfigProcessor.java b/consul/deployment/src/main/java/io/quarkus/consul/config/ConsulConfigProcessor.java
index 55642c0..7c0e3a5 100644
--- a/consul/deployment/src/main/java/io/quarkus/consul/config/ConsulConfigProcessor.java
+++ b/consul/deployment/src/main/java/io/quarkus/consul/config/ConsulConfigProcessor.java
@@ -2,18 +2,15 @@
 
 import org.jsoup.Connection.Response;
 
-import io.quarkus.consul.config.runtime.ConsulConfigRecorder;
+import io.quarkus.consul.config.runtime.ConsulConfigSourceFactoryBuilder;
 import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
-import io.quarkus.deployment.annotations.ExecutionTime;
-import io.quarkus.deployment.annotations.Record;
 import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem;
 import io.quarkus.deployment.builditem.FeatureBuildItem;
-import io.quarkus.deployment.builditem.RunTimeConfigurationSourceValueBuildItem;
+import io.quarkus.deployment.builditem.RunTimeConfigBuilderBuildItem;
 import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
 
 public class ConsulConfigProcessor {
-
     private static final String FEATURE = "consul-config";
 
     @BuildStep
@@ -32,10 +29,7 @@ public void registerForReflection(BuildProducer<ReflectiveClassBuildItem> reflec
     }
 
     @BuildStep
-    @Record(ExecutionTime.RUNTIME_INIT)
-    public RunTimeConfigurationSourceValueBuildItem configure(ConsulConfigRecorder recorder) {
-        return new RunTimeConfigurationSourceValueBuildItem(
-                recorder.configSources());
+    void consulConfigFactory(BuildProducer<RunTimeConfigBuilderBuildItem> runTimeConfigBuilder) {
+        runTimeConfigBuilder.produce(new RunTimeConfigBuilderBuildItem(ConsulConfigSourceFactoryBuilder.class.getName()));
     }
-
 }
diff --git a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfig.java b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfig.java
index 9803765..ab857f2 100644
--- a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfig.java
+++ b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfig.java
@@ -3,149 +3,132 @@
 import java.net.InetSocketAddress;
 import java.nio.file.Path;
 import java.time.Duration;
-import java.util.LinkedHashMap;
 import java.util.List;
-import java.util.Map;
 import java.util.Optional;
 
 import io.quarkus.runtime.annotations.ConfigGroup;
-import io.quarkus.runtime.annotations.ConfigItem;
 import io.quarkus.runtime.annotations.ConfigPhase;
 import io.quarkus.runtime.annotations.ConfigRoot;
+import io.quarkus.runtime.configuration.DurationConverter;
+import io.quarkus.runtime.configuration.InetSocketAddressConverter;
+import io.quarkus.runtime.configuration.PathConverter;
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithConverter;
+import io.smallrye.config.WithDefault;
 
-@ConfigRoot(name = "consul-config", phase = ConfigPhase.BOOTSTRAP)
-public class ConsulConfig {
+@ConfigMapping(prefix = "quarkus.consul-config")
+@ConfigRoot(phase = ConfigPhase.RUN_TIME)
+public interface ConsulConfig {
 
     /**
      * If set to true, the application will attempt to look up the configuration from Consul
      */
-    @ConfigItem(defaultValue = "false")
-    boolean enabled;
+    @WithDefault("false")
+    boolean enabled();
 
     /**
      * Consul agent related configuration
      */
-    @ConfigItem
-    AgentConfig agent;
+    AgentConfig agent();
 
     /**
      * Common prefix that all keys share when looking up the keys from Consul.
      * The prefix is <b>not</b> included in the keys of the user configuration
      */
-    @ConfigItem
-    Optional<String> prefix;
+    Optional<String> prefix();
 
     /**
      * Keys whose value is a raw string.
      * When this is used, the keys that end up in the user configuration are the keys specified her with '/' replaced by '.'
      */
-    @ConfigItem
-    Optional<List<String>> rawValueKeys;
+    Optional<List<String>> rawValueKeys();
 
     /**
      * Keys whose value represents a properties file.
      * When this is used, the keys that end up in the user configuration are the keys of the properties file,
      * not these keys
      */
-    @ConfigItem
-    Optional<List<String>> propertiesValueKeys;
+    Optional<List<String>> propertiesValueKeys();
 
     /**
      * If set to true, the application will not start if any of the configured config sources cannot be located
      */
-    @ConfigItem(defaultValue = "true")
-    boolean failOnMissingKey;
-
-    Map<String, ValueType> keysAsMap() {
-        Map<String, ValueType> result = new LinkedHashMap<>();
-        if (rawValueKeys.isPresent()) {
-            for (String key : rawValueKeys.get()) {
-                result.put(key, ValueType.RAW);
-            }
-        }
-        if (propertiesValueKeys.isPresent()) {
-            for (String key : propertiesValueKeys.get()) {
-                result.put(key, ValueType.PROPERTIES);
-            }
-        }
-        return result;
-    }
+    @WithDefault("true")
+    boolean failOnMissingKey();
 
     @ConfigGroup
-    public static class AgentConfig {
+    interface AgentConfig {
 
         /**
          * Consul agent host
          */
-        @ConfigItem(defaultValue = "localhost:8500")
-        InetSocketAddress hostPort;
+        @WithDefault("localhost:8500")
+        @WithConverter(InetSocketAddressConverter.class)
+        InetSocketAddress hostPort();
 
         /**
          * Whether or not to use HTTPS when communicating with the agent
          */
-        @ConfigItem(defaultValue = "false")
-        boolean useHttps;
+        @WithDefault("false")
+        boolean useHttps();
 
         /**
          * Consul token to be provided when authentication is enabled
          */
-        @ConfigItem
-        Optional<String> token;
+        Optional<String> token();
 
         /**
          * TrustStore to be used containing the SSL certificate used by Consul agent
          * Can be either a classpath resource or a file system path
          */
-        @ConfigItem
-        public Optional<Path> trustStore;
+        @WithConverter(PathConverter.class)
+        Optional<Path> trustStore();
 
         /**
          * Password of TrustStore to be used containing the SSL certificate used by Consul agent
          */
-        @ConfigItem
-        public Optional<String> trustStorePassword;
+        Optional<String> trustStorePassword();
 
         /**
          * KeyStore to be used containing the SSL certificate for authentication with Consul agent
          * Can be either a classpath resource or a file system path
          */
-        @ConfigItem
-        public Optional<Path> keyStore;
+        @WithConverter(PathConverter.class)
+        Optional<Path> keyStore();
 
         /**
          * Password of KeyStore to be used containing the SSL certificate for authentication with Consul agent
          */
-        @ConfigItem
-        public Optional<String> keyStorePassword;
+        Optional<String> keyStorePassword();
 
         /**
          * Password to recover key from KeyStore for SSL client authentication with Consul agent
          * If no value is provided, the key-store-password will be used
          */
-        @ConfigItem
-        public Optional<String> keyPassword;
+        Optional<String> keyPassword();
 
         /**
          * When using HTTPS and no keyStore has been specified, whether or not to trust all certificates
          */
-        @ConfigItem(defaultValue = "false")
-        boolean trustCerts;
+        @WithDefault("false")
+        boolean trustCerts();
 
         /**
          * The amount of time to wait when initially establishing a connection before giving up and timing out.
          * <p>
          * Specify `0` to wait indefinitely.
          */
-        @ConfigItem(defaultValue = "10S")
-        public Duration connectionTimeout;
+        @WithDefault("10s")
+        @WithConverter(DurationConverter.class)
+        Duration connectionTimeout();
 
         /**
          * The amount of time to wait for a read on a socket before an exception is thrown.
          * <p>
          * Specify `0` to wait indefinitely.
          */
-        @ConfigItem(defaultValue = "60S")
-        public Duration readTimeout;
+        @WithDefault("60s")
+        @WithConverter(DurationConverter.class)
+        Duration readTimeout();
     }
-
 }
diff --git a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigRecorder.java b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigRecorder.java
deleted file mode 100644
index e26e975..0000000
--- a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigRecorder.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package io.quarkus.consul.config.runtime;
-
-import java.util.Collections;
-
-import org.eclipse.microprofile.config.spi.ConfigSource;
-import org.eclipse.microprofile.config.spi.ConfigSourceProvider;
-import org.jboss.logging.Logger;
-
-import io.quarkus.runtime.RuntimeValue;
-import io.quarkus.runtime.annotations.Recorder;
-
-@Recorder
-public class ConsulConfigRecorder {
-
-    private static final Logger log = Logger.getLogger(ConsulConfigRecorder.class);
-
-    final ConsulConfig consulConfig;
-
-    public ConsulConfigRecorder(ConsulConfig consulConfig) {
-        this.consulConfig = consulConfig;
-    }
-
-    public RuntimeValue<ConfigSourceProvider> configSources() {
-        if (!consulConfig.enabled) {
-            log.debug(
-                    "No attempt will be made to obtain configuration from Consul because the functionality has been disabled via configuration");
-            return emptyRuntimeValue();
-        }
-
-        return new RuntimeValue<>(
-                new ConsulConfigSourceProvider(consulConfig));
-    }
-
-    private RuntimeValue<ConfigSourceProvider> emptyRuntimeValue() {
-        return new RuntimeValue<>(new EmptyConfigSourceProvider());
-    }
-
-    private static class EmptyConfigSourceProvider implements ConfigSourceProvider {
-
-        @Override
-        public Iterable<ConfigSource> getConfigSources(ClassLoader forClassLoader) {
-            return Collections.emptyList();
-        }
-    }
-}
diff --git a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigSourceProvider.java b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigSourceFactory.java
similarity index 52%
rename from consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigSourceProvider.java
rename to consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigSourceFactory.java
index 8bd60a0..0d9d3d2 100644
--- a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigSourceProvider.java
+++ b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigSourceFactory.java
@@ -2,46 +2,44 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.CompletionException;
 import java.util.function.Consumer;
 
 import org.eclipse.microprofile.config.spi.ConfigSource;
-import org.eclipse.microprofile.config.spi.ConfigSourceProvider;
 import org.jboss.logging.Logger;
 
+import io.smallrye.config.ConfigSourceContext;
+import io.smallrye.config.ConfigSourceFactory;
 import io.smallrye.mutiny.Uni;
 import io.smallrye.mutiny.groups.UniAwait;
 
-class ConsulConfigSourceProvider implements ConfigSourceProvider {
+class ConsulConfigSourceFactory implements ConfigSourceFactory.ConfigurableConfigSourceFactory<ConsulConfig> {
+    private static final Logger log = Logger.getLogger(ConsulConfigSourceFactory.class);
 
-    private static final Logger log = Logger.getLogger(ConsulConfigSourceProvider.class);
-
-    private final ConsulConfig config;
-
-    private final ConsulConfigGateway consulConfigGateway;
-    private final ResponseConfigSourceUtil responseConfigSourceUtil;
-
-    public ConsulConfigSourceProvider(ConsulConfig config) {
-        this(config, new VertxConsulConfigGateway(config), new ResponseConfigSourceUtil());
-    }
-
-    // visible for testing
-    ConsulConfigSourceProvider(ConsulConfig config, ConsulConfigGateway consulConfigGateway) {
-        this(config, consulConfigGateway, new ResponseConfigSourceUtil());
-    }
+    @Override
+    public Iterable<ConfigSource> getConfigSources(final ConfigSourceContext context, final ConsulConfig config) {
+        if (!config.enabled()) {
+            return Collections.emptyList();
+        }
 
-    private ConsulConfigSourceProvider(ConsulConfig config, ConsulConfigGateway consulConfigGateway,
-            ResponseConfigSourceUtil responseConfigSourceUtil) {
-        this.config = config;
-        this.consulConfigGateway = consulConfigGateway;
-        this.responseConfigSourceUtil = responseConfigSourceUtil;
+        return getConfigSources(config, new VertxConsulConfigGateway(config));
     }
 
-    @Override
-    public Iterable<ConfigSource> getConfigSources(ClassLoader cl) {
-        Map<String, ValueType> keys = config.keysAsMap();
+    Iterable<ConfigSource> getConfigSources(ConsulConfig config, ConsulConfigGateway consulConfigGateway) {
+        Map<String, ValueType> keys = new LinkedHashMap<>();
+        if (config.rawValueKeys().isPresent()) {
+            for (String key : config.rawValueKeys().get()) {
+                keys.put(key, ValueType.RAW);
+            }
+        }
+        if (config.propertiesValueKeys().isPresent()) {
+            for (String key : config.propertiesValueKeys().get()) {
+                keys.put(key, ValueType.PROPERTIES);
+            }
+        }
         if (keys.isEmpty()) {
             log.debug("No keys were configured for config source lookup");
             return Collections.emptyList();
@@ -52,17 +50,15 @@ public Iterable<ConfigSource> getConfigSources(ClassLoader cl) {
         List<Uni<?>> allUnis = new ArrayList<>();
 
         for (Map.Entry<String, ValueType> entry : keys.entrySet()) {
-            String fullKey = config.prefix.isPresent() ? config.prefix.get() + "/" + entry.getKey() : entry.getKey();
+            String fullKey = config.prefix().isPresent() ? config.prefix().get() + "/" + entry.getKey() : entry.getKey();
             allUnis.add(consulConfigGateway.getValue(fullKey).invoke(new Consumer<Response>() {
                 @Override
                 public void accept(Response response) {
                     if (response != null) {
-                        result.add(
-                                responseConfigSourceUtil.toConfigSource(response, entry.getValue(),
-                                        config.prefix));
+                        result.add(ResponseConfigSourceUtil.toConfigSource(response, entry.getValue(), config.prefix()));
                     } else {
                         String message = "Key '" + fullKey + "' not found in Consul.";
-                        if (config.failOnMissingKey) {
+                        if (config.failOnMissingKey()) {
                             throw new RuntimeException(message);
                         } else {
                             log.info(message);
@@ -74,10 +70,10 @@ public void accept(Response response) {
 
         try {
             UniAwait<Void> await = Uni.combine().all().unis(allUnis).discardItems().await();
-            if (config.agent.connectionTimeout.isZero() && config.agent.readTimeout.isZero()) {
+            if (config.agent().connectionTimeout().isZero() && config.agent().readTimeout().isZero()) {
                 await.indefinitely();
             } else {
-                await.atMost(config.agent.connectionTimeout.plus(config.agent.readTimeout.multipliedBy(2)));
+                await.atMost(config.agent().connectionTimeout().plus(config.agent().readTimeout().multipliedBy(2)));
             }
         } catch (CompletionException e) {
             throw new RuntimeException("An error occurred while attempting to fetch configuration from Consul.", e);
diff --git a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigSourceFactoryBuilder.java b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigSourceFactoryBuilder.java
new file mode 100644
index 0000000..478d963
--- /dev/null
+++ b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ConsulConfigSourceFactoryBuilder.java
@@ -0,0 +1,11 @@
+package io.quarkus.consul.config.runtime;
+
+import io.quarkus.runtime.configuration.ConfigBuilder;
+import io.smallrye.config.SmallRyeConfigBuilder;
+
+public class ConsulConfigSourceFactoryBuilder implements ConfigBuilder {
+    @Override
+    public SmallRyeConfigBuilder configBuilder(final SmallRyeConfigBuilder builder) {
+        return builder.withSources(new ConsulConfigSourceFactory());
+    }
+}
diff --git a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ResponseConfigSourceUtil.java b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ResponseConfigSourceUtil.java
index 68f92e5..1ee478b 100644
--- a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ResponseConfigSourceUtil.java
+++ b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/ResponseConfigSourceUtil.java
@@ -19,7 +19,7 @@ class ResponseConfigSourceUtil {
 
     private static final int ORDINAL = 270; // this is higher than the file system or jar ordinals, but lower than env vars
 
-    public ConfigSource toConfigSource(Response response, ValueType valueType, Optional<String> prefix) {
+    public static ConfigSource toConfigSource(Response response, ValueType valueType, Optional<String> prefix) {
         if (log.isDebugEnabled()) {
             log.debug("Attempting to convert data of key " + " '" + response.getKey()
                     + "' to a list of ConfigSource objects");
@@ -40,7 +40,7 @@ public ConfigSource toConfigSource(Response response, ValueType valueType, Optio
         return result;
     }
 
-    private String keyWithoutPrefix(Response response, Optional<String> prefix) {
+    private static String keyWithoutPrefix(Response response, Optional<String> prefix) {
         return prefix.isPresent() ? response.getKey().replace(prefix.get() + "/", "") : response.getKey();
     }
 
diff --git a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/VertxConsulConfigGateway.java b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/VertxConsulConfigGateway.java
index fc58433..23dcff8 100644
--- a/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/VertxConsulConfigGateway.java
+++ b/consul/runtime/src/main/java/io/quarkus/consul/config/runtime/VertxConsulConfigGateway.java
@@ -37,7 +37,7 @@ public class VertxConsulConfigGateway implements ConsulConfigGateway {
     public VertxConsulConfigGateway(ConsulConfig consulConfig) {
         this.consulConfig = consulConfig;
         this.vertx = createVertxInstance();
-        this.webClient = createHttpClient(vertx, consulConfig.agent);
+        this.webClient = createHttpClient(vertx, consulConfig.agent());
     }
 
     private Vertx createVertxInstance() {
@@ -64,15 +64,15 @@ private Vertx createVertxInstance() {
     public static WebClient createHttpClient(Vertx vertx, ConsulConfig.AgentConfig agentConfig) {
 
         WebClientOptions webClientOptions = new WebClientOptions()
-                .setConnectTimeout((int) agentConfig.connectionTimeout.toMillis())
-                .setIdleTimeout((int) agentConfig.readTimeout.getSeconds());
+                .setConnectTimeout((int) agentConfig.connectionTimeout().toMillis())
+                .setIdleTimeout((int) agentConfig.readTimeout().getSeconds());
 
-        boolean trustAll = agentConfig.trustCerts;
+        boolean trustAll = agentConfig.trustCerts();
         try {
-            if (agentConfig.trustStore.isPresent()) {
-                Path trustStorePath = agentConfig.trustStore.get();
+            if (agentConfig.trustStore().isPresent()) {
+                Path trustStorePath = agentConfig.trustStore().get();
                 String type = determineStoreType(trustStorePath);
-                KeyStoreOptionsBase storeOptions = storeOptions(trustStorePath, agentConfig.trustStorePassword,
+                KeyStoreOptionsBase storeOptions = storeOptions(trustStorePath, agentConfig.trustStorePassword(),
                         createStoreOptions(type));
                 if (isPfx(type)) {
                     webClientOptions.setPfxTrustOptions((PfxOptions) storeOptions);
@@ -81,10 +81,10 @@ public static WebClient createHttpClient(Vertx vertx, ConsulConfig.AgentConfig a
                 }
             } else if (trustAll) {
                 skipVerify(webClientOptions);
-            } else if (agentConfig.keyStore.isPresent()) {
-                Path trustStorePath = agentConfig.keyStore.get();
+            } else if (agentConfig.keyStore().isPresent()) {
+                Path trustStorePath = agentConfig.keyStore().get();
                 String type = determineStoreType(trustStorePath);
-                KeyStoreOptionsBase storeOptions = storeOptions(trustStorePath, agentConfig.keyStorePassword,
+                KeyStoreOptionsBase storeOptions = storeOptions(trustStorePath, agentConfig.keyStorePassword(),
                         createStoreOptions(type));
                 if (isPfx(type)) {
                     webClientOptions.setPfxTrustOptions((PfxOptions) storeOptions);
@@ -159,11 +159,12 @@ private static byte[] allBytes(InputStream inputStream) throws Exception {
     @Override
     public Uni<Response> getValue(String key) {
         HttpRequest<Buffer> request = webClient
-                .get(consulConfig.agent.hostPort.getPort(), consulConfig.agent.hostPort.getHostString(), "/v1/kv/" + key)
-                .ssl(consulConfig.agent.useHttps)
+                .get(consulConfig.agent().hostPort().getPort(), consulConfig.agent().hostPort().getHostString(),
+                        "/v1/kv/" + key)
+                .ssl(consulConfig.agent().useHttps())
                 .putHeader("Accept", "application/json;charset=UTF-8");
-        if (consulConfig.agent.token.isPresent()) {
-            request.putHeader("Authorization", "Bearer " + consulConfig.agent.token.get());
+        if (consulConfig.agent().token().isPresent()) {
+            request.putHeader("Authorization", "Bearer " + consulConfig.agent().token().get());
         }
 
         log.debug("Attempting to look up value of key '" + key + "' from Consul.");
diff --git a/consul/runtime/src/test/java/io/quarkus/consul/config/runtime/ConsulConfigSourceProviderTest.java b/consul/runtime/src/test/java/io/quarkus/consul/config/runtime/ConsulConfigSourceFactoryTest.java
similarity index 70%
rename from consul/runtime/src/test/java/io/quarkus/consul/config/runtime/ConsulConfigSourceProviderTest.java
rename to consul/runtime/src/test/java/io/quarkus/consul/config/runtime/ConsulConfigSourceFactoryTest.java
index fff9a6a..0bb050d 100644
--- a/consul/runtime/src/test/java/io/quarkus/consul/config/runtime/ConsulConfigSourceProviderTest.java
+++ b/consul/runtime/src/test/java/io/quarkus/consul/config/runtime/ConsulConfigSourceFactoryTest.java
@@ -12,8 +12,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.io.IOException;
-import java.time.Duration;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Optional;
@@ -21,18 +19,17 @@
 import org.eclipse.microprofile.config.spi.ConfigSource;
 import org.junit.jupiter.api.Test;
 
-class ConsulConfigSourceProviderTest {
+import io.quarkus.consul.config.runtime.ConsulConfig.AgentConfig;
 
+class ConsulConfigSourceFactoryTest {
     private static final int EXPECTED_ORDINAL = 270;
 
     @Test
-    void testEmptyKeys() throws IOException {
-        ConsulConfig config = defaultConfig();
-
+    void testEmptyKeys() {
+        ConsulConfig config = mock(ConsulConfig.class);
         ConsulConfigGateway mockGateway = mock(ConsulConfigGateway.class);
-        ConsulConfigSourceProvider sut = new ConsulConfigSourceProvider(config, mockGateway);
 
-        Iterable<ConfigSource> configSources = sut.getConfigSources(null);
+        Iterable<ConfigSource> configSources = new ConsulConfigSourceFactory().getConfigSources(config, mockGateway);
         assertThat(configSources).isEmpty();
 
         // no interactions with Consul should have taken place
@@ -40,21 +37,21 @@ void testEmptyKeys() throws IOException {
     }
 
     @Test
-    void testWithMissingKeysAndFailureConfigured() throws IOException {
-        ConsulConfig config = defaultConfig();
-        config.rawValueKeys = keyValues("some/first", "some/second");
-        config.failOnMissingKey = true;
+    void testWithMissingKeysAndFailureConfigured() {
+        ConsulConfig config = mock(ConsulConfig.class);
+        when(config.rawValueKeys()).thenReturn(keyValues("some/first", "some/second"));
+        when(config.failOnMissingKey()).thenReturn(true);
+        AgentConfig agentConfig = mock(AgentConfig.class);
+        when(config.agent()).thenReturn(agentConfig);
 
         ConsulConfigGateway mockGateway = mock(ConsulConfigGateway.class);
-        // make sure the first is is properly resolved
+        // make sure the first is properly resolved
         when(mockGateway.getValue("some/first")).thenReturn(validResponse("some/first", "whatever"));
         // make sure the second is not resolved
         when(mockGateway.getValue("some/second")).thenReturn(emptyResponse());
 
-        ConsulConfigSourceProvider sut = new ConsulConfigSourceProvider(config, mockGateway);
-
         assertThatThrownBy(() -> {
-            sut.getConfigSources(null);
+            new ConsulConfigSourceFactory().getConfigSources(config, mockGateway);
         }).isInstanceOf(RuntimeException.class).hasMessageContaining("some/second");
 
         //both of the keys should have been resolved because we resolve keys in the order they were given by the user
@@ -63,22 +60,21 @@ void testWithMissingKeysAndFailureConfigured() throws IOException {
     }
 
     @Test
-    void testWithMissingKeysAndIgnoreFailureConfigured() throws IOException {
-        ConsulConfig config = defaultConfig();
-        config.rawValueKeys = keyValues("some/first", "some/second", "some/third");
-        config.failOnMissingKey = false;
+    void testWithMissingKeysAndIgnoreFailureConfigured() {
+        ConsulConfig config = mock(ConsulConfig.class);
+        when(config.rawValueKeys()).thenReturn(keyValues("some/first", "some/second", "some/third"));
+        AgentConfig agentConfig = mock(AgentConfig.class);
+        when(config.agent()).thenReturn(agentConfig);
 
         ConsulConfigGateway mockGateway = mock(ConsulConfigGateway.class);
-        // make sure the first is is properly resolved
+        // make sure the first is properly resolved
         when(mockGateway.getValue("some/first")).thenReturn(validResponse("some/first", "whatever"));
         // make sure the second is not resolved
         when(mockGateway.getValue("some/second")).thenReturn(emptyResponse());
-        // make sure the third is is properly resolved
+        // make sure the third is properly resolved
         when(mockGateway.getValue("some/third")).thenReturn(validResponse("some/third", "other"));
 
-        ConsulConfigSourceProvider sut = new ConsulConfigSourceProvider(config, mockGateway);
-
-        Iterable<ConfigSource> configSources = sut.getConfigSources(null);
+        Iterable<ConfigSource> configSources = new ConsulConfigSourceFactory().getConfigSources(config, mockGateway);
         assertThat(configSources).hasSize(2);
         assertThat(configSources).filteredOn(c -> c.getName().contains("first")).singleElement().satisfies(c -> {
             assertThat(c.getOrdinal()).isEqualTo(EXPECTED_ORDINAL);
@@ -96,9 +92,11 @@ void testWithMissingKeysAndIgnoreFailureConfigured() throws IOException {
     }
 
     @Test
-    void testRawKeysWithoutPrefix() throws IOException {
-        ConsulConfig config = defaultConfig();
-        config.rawValueKeys = keyValues("greeting/message", "greeting/name");
+    void testRawKeysWithoutPrefix() {
+        ConsulConfig config = mock(ConsulConfig.class);
+        when(config.rawValueKeys()).thenReturn(keyValues("greeting/message", "greeting/name"));
+        AgentConfig agentConfig = mock(AgentConfig.class);
+        when(config.agent()).thenReturn(agentConfig);
 
         ConsulConfigGateway mockGateway = mock(ConsulConfigGateway.class);
         when(mockGateway.getValue("greeting/message"))
@@ -106,9 +104,7 @@ void testRawKeysWithoutPrefix() throws IOException {
         when(mockGateway.getValue("greeting/name"))
                 .thenReturn(validResponse("greeting/name", "quarkus"));
 
-        ConsulConfigSourceProvider sut = new ConsulConfigSourceProvider(config, mockGateway);
-
-        Iterable<ConfigSource> configSources = sut.getConfigSources(null);
+        Iterable<ConfigSource> configSources = new ConsulConfigSourceFactory().getConfigSources(config, mockGateway);
         assertThat(configSources).hasSize(2);
         assertThat(configSources).filteredOn(c -> c.getName().contains("message")).singleElement().satisfies(c -> {
             assertThat(c.getOrdinal()).isEqualTo(EXPECTED_ORDINAL);
@@ -124,10 +120,12 @@ void testRawKeysWithoutPrefix() throws IOException {
     }
 
     @Test
-    void testRawKeysWithPrefix() throws IOException {
-        ConsulConfig config = defaultConfig();
-        config.prefix = Optional.of("whatever");
-        config.rawValueKeys = keyValues("greeting/message", "greeting/name");
+    void testRawKeysWithPrefix() {
+        ConsulConfig config = mock(ConsulConfig.class);
+        when(config.rawValueKeys()).thenReturn(keyValues("greeting/message", "greeting/name"));
+        when(config.prefix()).thenReturn(Optional.of("whatever"));
+        AgentConfig agentConfig = mock(AgentConfig.class);
+        when(config.agent()).thenReturn(agentConfig);
 
         ConsulConfigGateway mockGateway = mock(ConsulConfigGateway.class);
         when(mockGateway.getValue("whatever/greeting/message"))
@@ -135,9 +133,7 @@ void testRawKeysWithPrefix() throws IOException {
         when(mockGateway.getValue("whatever/greeting/name"))
                 .thenReturn(validResponse("whatever/greeting/name", "quarkus"));
 
-        ConsulConfigSourceProvider sut = new ConsulConfigSourceProvider(config, mockGateway);
-
-        Iterable<ConfigSource> configSources = sut.getConfigSources(null);
+        Iterable<ConfigSource> configSources = new ConsulConfigSourceFactory().getConfigSources(config, mockGateway);
         assertThat(configSources).hasSize(2);
         assertThat(configSources).filteredOn(c -> c.getName().contains("message")).singleElement().satisfies(c -> {
             assertThat(c.getOrdinal()).isEqualTo(EXPECTED_ORDINAL);
@@ -153,9 +149,11 @@ void testRawKeysWithPrefix() throws IOException {
     }
 
     @Test
-    void testPropertiesKeysWithoutPrefix() throws IOException {
-        ConsulConfig config = defaultConfig();
-        config.propertiesValueKeys = keyValues("first", "second");
+    void testPropertiesKeysWithoutPrefix() {
+        ConsulConfig config = mock(ConsulConfig.class);
+        when(config.propertiesValueKeys()).thenReturn(keyValues("first", "second"));
+        AgentConfig agentConfig = mock(AgentConfig.class);
+        when(config.agent()).thenReturn(agentConfig);
 
         ConsulConfigGateway mockGateway = mock(ConsulConfigGateway.class);
         when(mockGateway.getValue("first"))
@@ -163,9 +161,7 @@ void testPropertiesKeysWithoutPrefix() throws IOException {
         when(mockGateway.getValue("second"))
                 .thenReturn(validResponse("second", "other.key=value"));
 
-        ConsulConfigSourceProvider sut = new ConsulConfigSourceProvider(config, mockGateway);
-
-        Iterable<ConfigSource> configSources = sut.getConfigSources(null);
+        Iterable<ConfigSource> configSources = new ConsulConfigSourceFactory().getConfigSources(config, mockGateway);
         assertThat(configSources).hasSize(2);
         assertThat(configSources).filteredOn(c -> c.getName().contains("first")).singleElement().satisfies(c -> {
             assertThat(c.getOrdinal()).isEqualTo(EXPECTED_ORDINAL);
@@ -182,10 +178,12 @@ void testPropertiesKeysWithoutPrefix() throws IOException {
     }
 
     @Test
-    void testPropertiesKeysWithPrefix() throws IOException {
-        ConsulConfig config = defaultConfig();
-        config.prefix = Optional.of("config");
-        config.propertiesValueKeys = keyValues("first", "second");
+    void testPropertiesKeysWithPrefix() {
+        ConsulConfig config = mock(ConsulConfig.class);
+        when(config.propertiesValueKeys()).thenReturn(keyValues("first", "second"));
+        when(config.prefix()).thenReturn(Optional.of("config"));
+        AgentConfig agentConfig = mock(AgentConfig.class);
+        when(config.agent()).thenReturn(agentConfig);
 
         ConsulConfigGateway mockGateway = mock(ConsulConfigGateway.class);
         when(mockGateway.getValue("config/first"))
@@ -193,9 +191,7 @@ void testPropertiesKeysWithPrefix() throws IOException {
         when(mockGateway.getValue("config/second"))
                 .thenReturn(validResponse("config/second", "other.key=value"));
 
-        ConsulConfigSourceProvider sut = new ConsulConfigSourceProvider(config, mockGateway);
-
-        Iterable<ConfigSource> configSources = sut.getConfigSources(null);
+        Iterable<ConfigSource> configSources = new ConsulConfigSourceFactory().getConfigSources(config, mockGateway);
         assertThat(configSources).hasSize(2);
         assertThat(configSources).filteredOn(c -> c.getName().contains("first")).singleElement().satisfies(c -> {
             assertThat(c.getOrdinal()).isEqualTo(EXPECTED_ORDINAL);
@@ -211,21 +207,7 @@ void testPropertiesKeysWithPrefix() throws IOException {
         verify(mockGateway, times(1)).getValue("config/second");
     }
 
-    private ConsulConfig defaultConfig() {
-        ConsulConfig config = new ConsulConfig();
-        config.enabled = true;
-        config.failOnMissingKey = true;
-        config.rawValueKeys = Optional.empty();
-        config.propertiesValueKeys = Optional.empty();
-        config.prefix = Optional.empty();
-        config.agent = new ConsulConfig.AgentConfig();
-        config.agent.readTimeout = Duration.ofSeconds(10);
-        config.agent.connectionTimeout = Duration.ofSeconds(10);
-        return config;
-    }
-
     private Optional<List<String>> keyValues(String... keys) {
         return Optional.of(Arrays.asList(keys));
     }
-
 }
diff --git a/docs/modules/ROOT/pages/includes/attributes.adoc b/docs/modules/ROOT/pages/includes/attributes.adoc
index 37df079..d7776c5 100644
--- a/docs/modules/ROOT/pages/includes/attributes.adoc
+++ b/docs/modules/ROOT/pages/includes/attributes.adoc
@@ -1,4 +1,4 @@
-:quarkus-version: 2.10.0.Final
+:quarkus-version: 2.15.3.Final
 :quarkus-config-extensions-version: 1.1.0
 :maven-version: 3.8.1+
 
diff --git a/docs/modules/ROOT/pages/includes/quarkus-consul-config.adoc b/docs/modules/ROOT/pages/includes/quarkus-consul-config.adoc
index 1050af9..c16778d 100644
--- a/docs/modules/ROOT/pages/includes/quarkus-consul-config.adoc
+++ b/docs/modules/ROOT/pages/includes/quarkus-consul-config.adoc
@@ -1,3 +1,5 @@
+
+:summaryTableId: quarkus-consul-config
 [.configuration-legend]
 icon:lock[title=Fixed at build time] Configuration property fixed at build time - All other configuration properties are overridable at runtime
 [.configuration-reference.searchable, cols="80,.^10,.^10"]
@@ -13,6 +15,13 @@ a| [[quarkus-consul-config_quarkus.consul-config.enabled]]`link:#quarkus-consul-
 [.description]
 --
 If set to true, the application will attempt to look up the configuration from Consul
+
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_ENABLED+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_ENABLED+++`
+endif::add-copy-button-to-env-var[]
 --|boolean 
 |`false`
 
@@ -21,8 +30,13 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.host-port]]`link:#quarkus
 
 [.description]
 --
-Consul agent host
---|host:port 
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_HOST_PORT+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_HOST_PORT+++`
+endif::add-copy-button-to-env-var[]
+--|InetSocketAddress 
 |`localhost:8500`
 
 
@@ -30,7 +44,12 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.use-https]]`link:#quarkus
 
 [.description]
 --
-Whether or not to use HTTPS when communicating with the agent
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_USE_HTTPS+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_USE_HTTPS+++`
+endif::add-copy-button-to-env-var[]
 --|boolean 
 |`false`
 
@@ -39,7 +58,12 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.token]]`link:#quarkus-con
 
 [.description]
 --
-Consul token to be provided when authentication is enabled
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_TOKEN+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_TOKEN+++`
+endif::add-copy-button-to-env-var[]
 --|string 
 |
 
@@ -48,7 +72,12 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.trust-store]]`link:#quark
 
 [.description]
 --
-TrustStore to be used containing the SSL certificate used by Consul agent Can be either a classpath resource or a file system path
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_TRUST_STORE+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_TRUST_STORE+++`
+endif::add-copy-button-to-env-var[]
 --|path 
 |
 
@@ -57,7 +86,12 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.trust-store-password]]`li
 
 [.description]
 --
-Password of TrustStore to be used containing the SSL certificate used by Consul agent
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_TRUST_STORE_PASSWORD+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_TRUST_STORE_PASSWORD+++`
+endif::add-copy-button-to-env-var[]
 --|string 
 |
 
@@ -66,7 +100,12 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.key-store]]`link:#quarkus
 
 [.description]
 --
-KeyStore to be used containing the SSL certificate for authentication with Consul agent Can be either a classpath resource or a file system path
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_KEY_STORE+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_KEY_STORE+++`
+endif::add-copy-button-to-env-var[]
 --|path 
 |
 
@@ -75,7 +114,12 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.key-store-password]]`link
 
 [.description]
 --
-Password of KeyStore to be used containing the SSL certificate for authentication with Consul agent
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_KEY_STORE_PASSWORD+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_KEY_STORE_PASSWORD+++`
+endif::add-copy-button-to-env-var[]
 --|string 
 |
 
@@ -84,7 +128,12 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.key-password]]`link:#quar
 
 [.description]
 --
-Password to recover key from KeyStore for SSL client authentication with Consul agent If no value is provided, the key-store-password will be used
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_KEY_PASSWORD+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_KEY_PASSWORD+++`
+endif::add-copy-button-to-env-var[]
 --|string 
 |
 
@@ -93,7 +142,12 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.trust-certs]]`link:#quark
 
 [.description]
 --
-When using HTTPS and no keyStore has been specified, whether or not to trust all certificates
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_TRUST_CERTS+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_TRUST_CERTS+++`
+endif::add-copy-button-to-env-var[]
 --|boolean 
 |`false`
 
@@ -102,22 +156,28 @@ a| [[quarkus-consul-config_quarkus.consul-config.agent.connection-timeout]]`link
 
 [.description]
 --
-The amount of time to wait when initially establishing a connection before giving up and timing out. 
- Specify `0` to wait indefinitely.
---|link:https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html[Duration]
-  link:#duration-note-anchor[icon:question-circle[], title=More information about the Duration format]
-|`10S`
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_CONNECTION_TIMEOUT+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_CONNECTION_TIMEOUT+++`
+endif::add-copy-button-to-env-var[]
+--|Duration 
+|`10s`
 
 
 a| [[quarkus-consul-config_quarkus.consul-config.agent.read-timeout]]`link:#quarkus-consul-config_quarkus.consul-config.agent.read-timeout[quarkus.consul-config.agent.read-timeout]`
 
 [.description]
 --
-The amount of time to wait for a read on a socket before an exception is thrown. 
- Specify `0` to wait indefinitely.
---|link:https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html[Duration]
-  link:#duration-note-anchor[icon:question-circle[], title=More information about the Duration format]
-|`60S`
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_AGENT_READ_TIMEOUT+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_AGENT_READ_TIMEOUT+++`
+endif::add-copy-button-to-env-var[]
+--|Duration 
+|`60s`
 
 
 a| [[quarkus-consul-config_quarkus.consul-config.prefix]]`link:#quarkus-consul-config_quarkus.consul-config.prefix[quarkus.consul-config.prefix]`
@@ -125,6 +185,13 @@ a| [[quarkus-consul-config_quarkus.consul-config.prefix]]`link:#quarkus-consul-c
 [.description]
 --
 Common prefix that all keys share when looking up the keys from Consul. The prefix is *not* included in the keys of the user configuration
+
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_PREFIX+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_PREFIX+++`
+endif::add-copy-button-to-env-var[]
 --|string 
 |
 
@@ -134,6 +201,13 @@ a| [[quarkus-consul-config_quarkus.consul-config.raw-value-keys]]`link:#quarkus-
 [.description]
 --
 Keys whose value is a raw string. When this is used, the keys that end up in the user configuration are the keys specified her with '/' replaced by '.'
+
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_RAW_VALUE_KEYS+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_RAW_VALUE_KEYS+++`
+endif::add-copy-button-to-env-var[]
 --|list of string 
 |
 
@@ -143,6 +217,13 @@ a| [[quarkus-consul-config_quarkus.consul-config.properties-value-keys]]`link:#q
 [.description]
 --
 Keys whose value represents a properties file. When this is used, the keys that end up in the user configuration are the keys of the properties file, not these keys
+
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_PROPERTIES_VALUE_KEYS+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_PROPERTIES_VALUE_KEYS+++`
+endif::add-copy-button-to-env-var[]
 --|list of string 
 |
 
@@ -152,20 +233,14 @@ a| [[quarkus-consul-config_quarkus.consul-config.fail-on-missing-key]]`link:#qua
 [.description]
 --
 If set to true, the application will not start if any of the configured config sources cannot be located
+
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CONSUL_CONFIG_FAIL_ON_MISSING_KEY+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CONSUL_CONFIG_FAIL_ON_MISSING_KEY+++`
+endif::add-copy-button-to-env-var[]
 --|boolean 
 |`true`
 
-|===
-ifndef::no-duration-note[]
-[NOTE]
-[[duration-note-anchor]]
-.About the Duration format
-====
-The format for durations uses the standard `java.time.Duration` format.
-You can learn more about it in the link:https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html#parse-java.lang.CharSequence-[Duration#parse() javadoc].
-
-You can also provide duration values starting with a number.
-In this case, if the value consists only of a number, the converter treats the value as seconds.
-Otherwise, `PT` is implicitly prepended to the value to obtain a standard `java.time.Duration` format.
-====
-endif::no-duration-note[]
+|===
\ No newline at end of file
diff --git a/jdbc/deployment/src/main/java/io/quarkiverse/config/jdbc/deployment/ConfigExtensionsProcessor.java b/jdbc/deployment/src/main/java/io/quarkiverse/config/jdbc/deployment/ConfigExtensionsProcessor.java
index 28fe65f..b6e3808 100644
--- a/jdbc/deployment/src/main/java/io/quarkiverse/config/jdbc/deployment/ConfigExtensionsProcessor.java
+++ b/jdbc/deployment/src/main/java/io/quarkiverse/config/jdbc/deployment/ConfigExtensionsProcessor.java
@@ -1,6 +1,5 @@
 package io.quarkiverse.config.jdbc.deployment;
 
-import io.quarkiverse.config.jdbc.runtime.JdbcConfigConfig;
 import io.quarkiverse.config.jdbc.runtime.JdbcConfigSourceFactoryBuilder;
 import io.quarkus.deployment.annotations.BuildProducer;
 import io.quarkus.deployment.annotations.BuildStep;
@@ -18,7 +17,7 @@ FeatureBuildItem feature() {
     }
 
     @BuildStep
-    void jdbcConfigFactory(JdbcConfigConfig config,
+    void jdbcConfigFactory(
             BuildProducer<StaticInitConfigBuilderBuildItem> staticInitConfigBuilder,
             BuildProducer<RunTimeConfigBuilderBuildItem> runTimeConfigBuilder) {
         staticInitConfigBuilder.produce(new StaticInitConfigBuilderBuildItem(JdbcConfigSourceFactoryBuilder.class.getName()));
diff --git a/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigConfig.java b/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigConfig.java
index d95994b..b8ba43c 100644
--- a/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigConfig.java
+++ b/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigConfig.java
@@ -1,93 +1,100 @@
 package io.quarkiverse.config.jdbc.runtime;
 
 import java.time.Duration;
-import java.util.Optional;
 
-import io.quarkus.runtime.annotations.ConfigItem;
 import io.quarkus.runtime.annotations.ConfigPhase;
 import io.quarkus.runtime.annotations.ConfigRoot;
+import io.quarkus.runtime.configuration.DurationConverter;
+import io.smallrye.config.ConfigMapping;
+import io.smallrye.config.WithConverter;
+import io.smallrye.config.WithDefault;
+import io.smallrye.config.WithName;
 
 /**
  * We don't really use this, because these are configurations for the config itself, so it causes a chicken / egg
  * problem, but we have it so the configurations can be properly documented.
- *
+ * <br>
  * The config itself is loaded using the ConfigSourceContext on the ConfigSourceFactory
  */
-@ConfigRoot(name = "config.source.jdbc", phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
-public class JdbcConfigConfig {
+@ConfigMapping(prefix = "quarkus.config.source.jdbc")
+@ConfigRoot(phase = ConfigPhase.BUILD_AND_RUN_TIME_FIXED)
+public interface JdbcConfigConfig {
 
     /**
      * If set to true, the application will attempt to look up the configuration from DB
      */
-    @ConfigItem(name = "enabled", defaultValue = "true")
-    public boolean enabled = true;
+    @WithDefault("true")
+    boolean enabled();
 
     /**
      * If set to true, the application will cache all looked up the configuration from DB in memory
      * If set to false, the application will always get the latest values from the DB
      */
-    @ConfigItem(name = "cache", defaultValue = "true")
-    public boolean cache = true;
+    @WithDefault("true")
+    boolean cache();
 
     /**
      * Table name for configuration records
      */
-    @ConfigItem(name = "table", defaultValue = "configuration")
-    public String table;
+    @WithDefault("configuration")
+    String table();
 
     /**
      * Name of the column containing the key
      */
-    @ConfigItem(name = "key", defaultValue = "configuration_key")
-    public String keyColumn;
+    @WithName("key")
+    @WithDefault("configuration_key")
+    String keyColumn();
 
     /**
      * Name of the column containing the value
      */
-    @ConfigItem(name = "value", defaultValue = "configuration_value")
-    public String valueColumn;
+    @WithName("value")
+    @WithDefault("configuration_value")
+    String valueColumn();
 
     /**
      * The datasource username, if not defined the username of the default datasource is used
      */
-    @ConfigItem(name = "username")
-    public Optional<String> username = Optional.empty();;
+    @WithDefault("${quarkus.datasource.username}")
+    String username();
 
     /**
      * The datasource password, if not defined the password of the default datasource is used
      */
-    @ConfigItem(name = "password")
-    public Optional<String> password = Optional.empty();;
+    @WithDefault("${quarkus.datasource.password}")
+    String password();
 
     /**
      * The datasource URL, if not defined the URL of the default datasource is used
      */
-    @ConfigItem(name = "url")
-    public Optional<String> url = Optional.empty();
+    @WithDefault("${quarkus.datasource.jdbc.url}")
+    String url();
 
     /**
      * The initial size of the pool. Usually you will want to set the initial size to match at least the
      * minimal size, but this is not enforced so to allow for architectures which prefer a lazy initialization
      * of the connections on boot, while being able to sustain a minimal pool size after boot.
      */
-    @ConfigItem(name = "initial-size", defaultValue = "0")
-    public int initialSize = 0;
+    @WithDefault("0")
+    int initialSize();
 
     /**
      * The datasource pool minimum size
      */
-    @ConfigItem(name = "min-size", defaultValue = "0")
-    public int minSize = 0;
+    @WithDefault("0")
+    int minSize();
 
     /**
      * The datasource pool maximum size
      */
-    @ConfigItem(name = "max-size", defaultValue = "5")
-    public int maxSize = 5;
+    @WithDefault("5")
+    int maxSize();
 
     /**
      * The timeout before cancelling the acquisition of a new connection
      */
-    @ConfigItem(name = "acquisition-timeout", defaultValue = "5")
-    public Duration acquisitionTimeout = Duration.ofSeconds(5);
+    @WithDefault("5")
+    @WithConverter(DurationConverter.class)
+    Duration acquisitionTimeout();
 }
diff --git a/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigSourceFactory.java b/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigSourceFactory.java
index bf7b6af..e510902 100644
--- a/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigSourceFactory.java
+++ b/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigSourceFactory.java
@@ -1,12 +1,8 @@
 package io.quarkiverse.config.jdbc.runtime;
 
 import java.sql.SQLException;
-import java.time.Duration;
-import java.util.ArrayList;
 import java.util.Collections;
-import java.util.List;
 import java.util.Map;
-import java.util.Optional;
 
 import org.eclipse.microprofile.config.spi.ConfigSource;
 import org.jboss.logging.Logger;
@@ -15,94 +11,26 @@
 import io.smallrye.config.ConfigSourceFactory;
 import io.smallrye.config.common.MapBackedConfigSource;
 
-public class JdbcConfigSourceFactory implements ConfigSourceFactory {
-
+public class JdbcConfigSourceFactory implements ConfigSourceFactory.ConfigurableConfigSourceFactory<JdbcConfigConfig> {
     private static final Logger log = Logger.getLogger(JdbcConfigSourceFactory.class);
 
     @Override
-    public Iterable<ConfigSource> getConfigSources(ConfigSourceContext context) {
-        try {
-            final JdbcConfigConfig config = populateConfig(context);
-            final Repository repository = new Repository(config);
-            return getConfigSource(config, repository);
-        } catch (SQLException e) {
-            log.warn("jdbc-config disabled. reason: " + e.getLocalizedMessage());
+    public Iterable<ConfigSource> getConfigSources(final ConfigSourceContext context, final JdbcConfigConfig config) {
+        if (!config.enabled()) {
             return Collections.emptyList();
         }
-    }
 
-    protected List<ConfigSource> getConfigSource(final JdbcConfigConfig config, final Repository repository) {
-        if (!config.enabled) {
+        try {
+            Repository repository = new Repository(config);
+            if (config.cache()) {
+                return Collections.singletonList(new InMemoryConfigSource("jdbc-config", repository.getAllConfigValues(), 400));
+            } else {
+                return Collections.singletonList(new JdbcConfigSource("jdbc-config", repository, 400));
+            }
+        } catch (SQLException e) {
+            log.warn("jdbc-config disabled. reason: " + e.getLocalizedMessage());
             return Collections.emptyList();
         }
-
-        final List<ConfigSource> list = new ArrayList<>();
-        final Map<String, String> result = repository.getAllConfigValues();
-
-        if (config.cache) {
-            list.add(new InMemoryConfigSource("jdbc-config", result, 400));
-        } else {
-            list.add(new JdbcConfigSource("jdbc-config", repository, 400));
-        }
-
-        return list;
-    }
-
-    private JdbcConfigConfig populateConfig(ConfigSourceContext context) {
-        final JdbcConfigConfig config = new JdbcConfigConfig();
-
-        // jdbc-config parameters
-        config.enabled = Boolean
-                .parseBoolean(Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.enabled").getValue())
-                        .orElse(String.valueOf(config.enabled)));
-
-        // short-circuit if config is disabled
-        if (!config.enabled) {
-            return config;
-        }
-
-        config.cache = Boolean.parseBoolean(Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.cache").getValue())
-                .orElse(String.valueOf(config.cache)));
-
-        // table, keyColumn, valueColumn
-        config.table = Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.table").getValue())
-                .orElse(config.table);
-        config.keyColumn = Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.key").getValue())
-                .orElse(config.keyColumn);
-        config.valueColumn = Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.value").getValue())
-                .orElse(config.valueColumn);
-
-        // connection parameters
-
-        // url, username, password (use default datasource values if jdbc-config values are not defined )
-        config.username = Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.username").getValue())
-                .or(() -> Optional.ofNullable(context.getValue("quarkus.datasource.username").getValue()));
-        config.password = Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.password").getValue())
-                .or(() -> Optional.ofNullable(context.getValue("quarkus.datasource.password").getValue()));
-        config.url = Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.url").getValue())
-                .or(() -> Optional.ofNullable(context.getValue("quarkus.datasource.jdbc.url").getValue()));
-
-        // initialSize, minSize, maxSize, acquisitionTimeout
-        config.initialSize = Integer
-                .parseInt(Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.initial-size").getValue())
-                        .orElse(String.valueOf(config.initialSize)));
-        config.minSize = Integer
-                .parseInt(Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.min-size").getValue())
-                        .orElse(String.valueOf(config.minSize)));
-        config.maxSize = Integer
-                .parseInt(Optional.ofNullable(context.getValue("quarkus.config.source.jdbc.max-size").getValue())
-                        .orElse(String.valueOf(config.maxSize)));
-
-        Optional<String> timeout = Optional
-                .ofNullable(context.getValue("quarkus.config.source.jdbc.acquisition-timeout").getValue());
-
-        // acquisitionTimeout (java.time.Duration) is allowed to be just numbers (seconds) or standard Duration format (PTXX)
-        if (timeout.isPresent() && timeout.get().matches("[0-9]+")) {
-            config.acquisitionTimeout = Duration.ofSeconds(Long.parseLong(timeout.get()));
-        } else {
-            config.acquisitionTimeout = Duration.parse(timeout.orElse(config.acquisitionTimeout.toString()));
-        }
-        return config;
     }
 
     private static final class InMemoryConfigSource extends MapBackedConfigSource {
diff --git a/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/Repository.java b/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/Repository.java
index 4e3aa48..2c75e5e 100644
--- a/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/Repository.java
+++ b/jdbc/runtime/src/main/java/io/quarkiverse/config/jdbc/runtime/Repository.java
@@ -93,25 +93,26 @@ private void prepareDataSource(final JdbcConfigConfig config) throws SQLExceptio
 
         // configure pool
         poolConfiguration
-                .initialSize(config.initialSize)
-                .minSize(config.initialSize)
-                .maxSize(config.maxSize)
-                .acquisitionTimeout(config.acquisitionTimeout);
+                .initialSize(config.initialSize())
+                .minSize(config.minSize())
+                .maxSize(config.maxSize())
+                .acquisitionTimeout(config.acquisitionTimeout());
 
         // configure supplier
         connectionFactoryConfiguration
-                .jdbcUrl(config.url.get())
-                .credential(new NamePrincipal(config.username.get()))
-                .credential(new SimplePassword(config.password.get()));
+                .jdbcUrl(config.url())
+                .credential(new NamePrincipal(config.username()))
+                .credential(new SimplePassword(config.password()));
 
         dataSource = AgroalDataSource.from(dataSourceConfiguration.get());
     }
 
     private void prepareQueries(final JdbcConfigConfig config) {
-        selectAllQuery = "SELECT conf." + config.keyColumn + ", conf." + config.valueColumn + " FROM " + config.table + " conf";
-        selectKeysQuery = "SELECT conf." + config.keyColumn + " FROM " + config.table + " conf";
-        selectValueQuery = "SELECT conf." + config.valueColumn + " FROM " + config.table + " conf WHERE conf."
-                + config.keyColumn + " = ?1";
+        selectAllQuery = "SELECT conf." + config.keyColumn() + ", conf." + config.valueColumn() + " FROM " + config.table()
+                + " conf";
+        selectKeysQuery = "SELECT conf." + config.keyColumn() + " FROM " + config.table() + " conf";
+        selectValueQuery = "SELECT conf." + config.valueColumn() + " FROM " + config.table() + " conf WHERE conf."
+                + config.keyColumn() + " = ?1";
     }
 
     @Override
diff --git a/jdbc/runtime/src/test/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigSourceFactoryTest.java b/jdbc/runtime/src/test/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigSourceFactoryTest.java
deleted file mode 100644
index 901d93b..0000000
--- a/jdbc/runtime/src/test/java/io/quarkiverse/config/jdbc/runtime/JdbcConfigSourceFactoryTest.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package io.quarkiverse.config.jdbc.runtime;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.microprofile.config.spi.ConfigSource;
-import org.junit.jupiter.api.DisplayName;
-import org.junit.jupiter.api.Test;
-
-public class JdbcConfigSourceFactoryTest {
-    private final JdbcConfigConfig config = mock(JdbcConfigConfig.class);
-    private final Repository repository = mock(Repository.class);
-
-    @Test
-    @DisplayName("Repository returns data")
-    void testOnStoredData() throws SQLException {
-        String key = "foo";
-        String value = "sample value";
-        JdbcConfigSourceFactory factory = new JdbcConfigSourceFactory();
-        Map<String, String> map = new HashMap<>();
-        map.put(key, value);
-
-        config.enabled = true;
-
-        when(repository.getAllConfigValues()).thenReturn(map);
-        when(repository.getValue(key)).thenReturn(value);
-
-        List<ConfigSource> configSources = factory.getConfigSource(config, repository);
-        assertEquals(1, configSources.size());
-
-        ConfigSource configSource = configSources.iterator().next();
-        assertEquals(value, configSource.getValue(key));
-
-    }
-
-    @Test
-    @DisplayName("On disabled datasource is empty")
-    void testDisabledJdbcConfig() {
-        JdbcConfigSourceFactory factory = new JdbcConfigSourceFactory();
-
-        config.enabled = false;
-
-        List<ConfigSource> configSources = factory.getConfigSource(config, repository);
-        assertTrue(configSources.isEmpty());
-
-    }
-
-}