diff --git a/docs/using-the-jdbc-driver/UsingTheJdbcDriver.md b/docs/using-the-jdbc-driver/UsingTheJdbcDriver.md
index 829b4f38a..85d0ae314 100644
--- a/docs/using-the-jdbc-driver/UsingTheJdbcDriver.md
+++ b/docs/using-the-jdbc-driver/UsingTheJdbcDriver.md
@@ -84,7 +84,7 @@ These parameters are applicable to any instance of the AWS Advanced JDBC Wrapper
| `user` | `String` | No | Database username. | `null` |
| `password` | `String` | No | Database password. | `null` |
| `wrapperDialect` | `String` | No | Please see [this page on database dialects](./DatabaseDialects.md), and whether you should include it. | `null` |
-| `wrapperLogUnclosedConnections` | `Boolean` | No | Allows the AWS Advanced JDBC Wrapper to capture a stacktrace for each connection that is opened. If the `finalize()` method is reached without the connection being closed, the stacktrace is printed to the log. This helps developers to detect and correct the source of potential connection leaks. | `false` |
+| `wrapperLogUnclosedConnections` | `Boolean` | No | Allows the AWS Advanced JDBC Wrapper to capture a stacktrace for each connection that is opened. If the connection is garbage collected without being closed, the stacktrace is printed to the log. This helps developers to detect and correct the source of potential connection leaks. | `false` |
| `loginTimeout` | `Integer` | No | Login timeout in milliseconds. | `null` |
| `connectTimeout` | `Integer` | No | Socket connect timeout in milliseconds. | `null` |
| `socketTimeout` | `Integer` | No | Socket timeout in milliseconds. | `null` |
@@ -98,6 +98,19 @@ These parameters are applicable to any instance of the AWS Advanced JDBC Wrapper
| `wrapperCaseSensitive`, `wrappercasesensitive` | `Boolean` | No | Allows the driver to change case sensitivity for parameter names in the connection string and in connection properties. Set parameter to `false` to allow case-insensitive parameter names. | `true` |
| `skipWrappingForPackages` | `String` | No | Register Java package names (separated by comma) which will be left unwrapped. This setting modifies all future connections established by the driver, not just a particular connection. | `com.pgvector` |
+## System Properties
+
+These Java system properties can be set using `-D` flags when starting the JVM to configure global behavior of the AWS Advanced JDBC Wrapper.
+
+| Property | Value | Description | Default Value |
+|---------------------------------|-----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------|
+| `aws.jdbc.cleanup.thread.ttl` | `Long` | Time-to-live in milliseconds for the cleanup thread that monitors unclosed connections. The thread will automatically stop after this period of inactivity to conserve resources. Only relevant when `wrapperLogUnclosedConnections` is enabled. | `30000` (30 seconds) |
+
+**Example:**
+```bash
+java -Daws.jdbc.cleanup.thread.ttl=60000 -jar myapp.jar
+```
+
## Plugins
The AWS Advanced JDBC Wrapper uses plugins to execute JDBC methods. You can think of a plugin as an extensible code module that adds extra logic around any JDBC method calls. The AWS Advanced JDBC Wrapper has a number of [built-in plugins](#list-of-available-plugins) available for use.
diff --git a/wrapper/src/main/java/software/amazon/jdbc/util/LazyCleaner.java b/wrapper/src/main/java/software/amazon/jdbc/util/LazyCleaner.java
new file mode 100644
index 000000000..682cc81d8
--- /dev/null
+++ b/wrapper/src/main/java/software/amazon/jdbc/util/LazyCleaner.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+ *
+ * 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.
+ */
+/* changes were made to move it into the software.amazon.jdbc.util package
+ *
+ * Copyright 2022 Juan Lopes
+ *
+ * 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 software.amazon.jdbc.util;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+import java.time.Duration;
+import java.util.concurrent.ThreadFactory;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.checkerframework.checker.nullness.qual.Nullable;
+
+public class LazyCleaner {
+ private static final Logger LOGGER = Logger.getLogger(LazyCleaner.class.getName());
+ private static final LazyCleaner instance =
+ new LazyCleaner(
+ Duration.ofMillis(Long.getLong("aws.jdbc.cleanup.thread.ttl", 30000)),
+ "AWS-JDBC-Cleaner"
+ );
+
+ public interface Cleanable {
+ void clean() throws T;
+ }
+
+ public interface CleaningAction {
+ void onClean(boolean leak) throws T;
+ }
+
+ private final ReferenceQueue