diff --git a/Cargo.lock b/Cargo.lock
index a596718df6a796d97bb50679976d7372d0219069..95d8175e20044dae16458ad848fed16fbb86d772 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -94,7 +94,7 @@ dependencies = [
  "mime",
  "percent-encoding",
  "pin-project 1.0.8",
- "rand",
+ "rand 0.7.3",
  "regex",
  "serde",
  "serde_json",
@@ -289,6 +289,17 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
+[[package]]
+name = "ahash"
+version = "0.7.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
+dependencies = [
+ "getrandom 0.2.3",
+ "once_cell",
+ "version_check 0.9.3",
+]
+
 [[package]]
 name = "aho-corasick"
 version = "0.7.18"
@@ -385,6 +396,35 @@ dependencies = [
  "event-listener",
 ]
 
+[[package]]
+name = "async-native-tls"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9e9e7a929bd34c68a82d58a4de7f86fffdaf97fb2af850162a7bb19dd7269b33"
+dependencies = [
+ "async-std",
+ "native-tls",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "async-process"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83137067e3a2a6a06d67168e49e68a0957d215410473a740cea95a2425c0b7c6"
+dependencies = [
+ "async-io",
+ "blocking",
+ "cfg-if 1.0.0",
+ "event-listener",
+ "futures-lite",
+ "libc",
+ "once_cell",
+ "signal-hook",
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "async-std"
 version = "1.10.0"
@@ -395,6 +435,7 @@ dependencies = [
  "async-global-executor",
  "async-io",
  "async-lock",
+ "async-process",
  "crossbeam-utils",
  "futures-channel",
  "futures-core",
@@ -429,6 +470,15 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "atoi"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "616896e05fc0e2649463a93a15183c6a16bf03413a7af88ef1285ddedfa9cda5"
+dependencies = [
+ "num-traits",
+]
+
 [[package]]
 name = "atomic-waker"
 version = "1.0.0"
@@ -470,7 +520,7 @@ dependencies = [
  "log",
  "mime",
  "percent-encoding",
- "rand",
+ "rand 0.7.3",
  "serde",
  "serde_json",
  "serde_urlencoded",
@@ -670,6 +720,22 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536"
 
+[[package]]
+name = "core-foundation"
+version = "0.9.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
+
 [[package]]
 name = "cpufeatures"
 version = "0.2.1"
@@ -679,6 +745,21 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "crc"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49fc9a695bca7f35f5f4c15cddc84415f66a74ea78eef08e90c5024f2b540e23"
+dependencies = [
+ "crc-catalog",
+]
+
+[[package]]
+name = "crc-catalog"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccaeedb56da03b09f598226e25e80088cb4cd25f316e6e4df7d695f0feeb1403"
+
 [[package]]
 name = "crc32fast"
 version = "1.3.0"
@@ -688,6 +769,26 @@ dependencies = [
  "cfg-if 1.0.0",
 ]
 
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4"
+dependencies = [
+ "cfg-if 1.0.0",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-queue"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b10ddc024425c88c2ad148c1b0fd53f4c6d38db9697c9f1588381212fa657c9"
+dependencies = [
+ "cfg-if 1.0.0",
+ "crossbeam-utils",
+]
+
 [[package]]
 name = "crossbeam-utils"
 version = "0.8.5"
@@ -736,6 +837,12 @@ version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0"
 
+[[package]]
+name = "dotenv"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f"
+
 [[package]]
 name = "either"
 version = "1.6.1"
@@ -796,6 +903,21 @@ version = "1.0.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
 [[package]]
 name = "form_urlencoded"
 version = "1.0.1"
@@ -852,6 +974,17 @@ version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d"
 
+[[package]]
+name = "futures-intrusive"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62007592ac46aa7c2b6416f7deb9a8a8f63a01e0f1d6e1787d5630170db2b63e"
+dependencies = [
+ "futures-core",
+ "lock_api",
+ "parking_lot",
+]
+
 [[package]]
 name = "futures-io"
 version = "0.3.17"
@@ -998,6 +1131,18 @@ name = "hashbrown"
 version = "0.11.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
+dependencies = [
+ "ahash",
+]
+
+[[package]]
+name = "hashlink"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf"
+dependencies = [
+ "hashbrown",
+]
 
 [[package]]
 name = "heck"
@@ -1017,6 +1162,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hex"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+
 [[package]]
 name = "hostname"
 version = "0.3.1"
@@ -1096,6 +1247,15 @@ dependencies = [
  "winreg",
 ]
 
+[[package]]
+name = "itertools"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3"
+dependencies = [
+ "either",
+]
+
 [[package]]
 name = "itoa"
 version = "0.4.8"
@@ -1154,6 +1314,17 @@ version = "0.2.112"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
 
+[[package]]
+name = "libsqlite3-sys"
+version = "0.22.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d"
+dependencies = [
+ "cc",
+ "pkg-config",
+ "vcpkg",
+]
+
 [[package]]
 name = "linked-hash-map"
 version = "0.5.4"
@@ -1222,6 +1393,12 @@ dependencies = [
  "unicase",
 ]
 
+[[package]]
+name = "minimal-lexical"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
+
 [[package]]
 name = "miniz_oxide"
 version = "0.4.4"
@@ -1274,6 +1451,24 @@ dependencies = [
  "ws2_32-sys",
 ]
 
+[[package]]
+name = "native-tls"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d"
+dependencies = [
+ "lazy_static",
+ "libc",
+ "log",
+ "openssl",
+ "openssl-probe",
+ "openssl-sys",
+ "schannel",
+ "security-framework",
+ "security-framework-sys",
+ "tempfile",
+]
+
 [[package]]
 name = "net2"
 version = "0.2.37"
@@ -1295,6 +1490,17 @@ dependencies = [
  "version_check 0.1.5",
 ]
 
+[[package]]
+name = "nom"
+version = "7.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1d11e1ef389c76fe5b81bcaf2ea32cf88b62bc494e19f493d0b30e7a930109"
+dependencies = [
+ "memchr",
+ "minimal-lexical",
+ "version_check 0.9.3",
+]
+
 [[package]]
 name = "num-integer"
 version = "0.1.44"
@@ -1336,6 +1542,39 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
 
+[[package]]
+name = "openssl"
+version = "0.10.38"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95"
+dependencies = [
+ "bitflags",
+ "cfg-if 1.0.0",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-probe"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.72"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb"
+dependencies = [
+ "autocfg",
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
 [[package]]
 name = "parking"
 version = "2.0.0"
@@ -1431,6 +1670,12 @@ version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
+[[package]]
+name = "pkg-config"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe"
+
 [[package]]
 name = "polling"
 version = "2.2.0"
@@ -1518,9 +1763,21 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
 dependencies = [
  "getrandom 0.1.16",
  "libc",
- "rand_chacha",
- "rand_core",
- "rand_hc",
+ "rand_chacha 0.2.2",
+ "rand_core 0.5.1",
+ "rand_hc 0.2.0",
+]
+
+[[package]]
+name = "rand"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8"
+dependencies = [
+ "libc",
+ "rand_chacha 0.3.1",
+ "rand_core 0.6.3",
+ "rand_hc 0.3.1",
 ]
 
 [[package]]
@@ -1530,7 +1787,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
 dependencies = [
  "ppv-lite86",
- "rand_core",
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rand_chacha"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+dependencies = [
+ "ppv-lite86",
+ "rand_core 0.6.3",
 ]
 
 [[package]]
@@ -1542,13 +1809,31 @@ dependencies = [
  "getrandom 0.1.16",
 ]
 
+[[package]]
+name = "rand_core"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
+dependencies = [
+ "getrandom 0.2.3",
+]
+
 [[package]]
 name = "rand_hc"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
 dependencies = [
- "rand_core",
+ "rand_core 0.5.1",
+]
+
+[[package]]
+name = "rand_hc"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7"
+dependencies = [
+ "rand_core 0.6.3",
 ]
 
 [[package]]
@@ -1583,6 +1868,15 @@ version = "0.6.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
 
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "resolv-conf"
 version = "0.7.0"
@@ -1617,12 +1911,45 @@ version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
 
+[[package]]
+name = "schannel"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
+dependencies = [
+ "lazy_static",
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "scopeguard"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
 
+[[package]]
+name = "security-framework"
+version = "2.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
 [[package]]
 name = "semver"
 version = "0.9.0"
@@ -1706,6 +2033,29 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d"
 
+[[package]]
+name = "sha2"
+version = "0.9.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b69f9a4c9740d74c5baa3fd2e547f9525fa8088a8a958e0ca2409a514e33f5fa"
+dependencies = [
+ "block-buffer",
+ "cfg-if 1.0.0",
+ "cpufeatures",
+ "digest",
+ "opaque-debug",
+]
+
+[[package]]
+name = "signal-hook"
+version = "0.3.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c35dfd12afb7828318348b8c408383cf5071a086c1d4ab1c0f9840ec92dbb922"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
 [[package]]
 name = "signal-hook-registry"
 version = "1.4.0"
@@ -1759,6 +2109,98 @@ dependencies = [
  "winapi 0.3.9",
 ]
 
+[[package]]
+name = "sqlformat"
+version = "0.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4b7922be017ee70900be125523f38bdd644f4f06a1b16e8fa5a8ee8c34bffd4"
+dependencies = [
+ "itertools",
+ "nom 7.1.0",
+ "unicode_categories",
+]
+
+[[package]]
+name = "sqlx"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7911b0031a0247af40095838002999c7a52fba29d9739e93326e71a5a1bc9d43"
+dependencies = [
+ "sqlx-core",
+ "sqlx-macros",
+]
+
+[[package]]
+name = "sqlx-core"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aec89bfaca8f7737439bad16d52b07f1ccd0730520d3bf6ae9d069fe4b641fb1"
+dependencies = [
+ "ahash",
+ "atoi",
+ "bitflags",
+ "byteorder",
+ "bytes 1.1.0",
+ "crc",
+ "crossbeam-channel",
+ "crossbeam-queue",
+ "crossbeam-utils",
+ "either",
+ "futures-channel",
+ "futures-core",
+ "futures-intrusive",
+ "futures-util",
+ "hashlink",
+ "hex",
+ "indexmap",
+ "itoa 0.4.8",
+ "libc",
+ "libsqlite3-sys",
+ "log",
+ "memchr",
+ "once_cell",
+ "parking_lot",
+ "percent-encoding",
+ "sha2",
+ "smallvec",
+ "sqlformat",
+ "sqlx-rt",
+ "stringprep",
+ "thiserror",
+ "url",
+ "whoami",
+]
+
+[[package]]
+name = "sqlx-macros"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "584866c833511b1a152e87a7ee20dee2739746f60c858b3c5209150bc4b466f5"
+dependencies = [
+ "dotenv",
+ "either",
+ "heck",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "sha2",
+ "sqlx-core",
+ "sqlx-rt",
+ "syn",
+ "url",
+]
+
+[[package]]
+name = "sqlx-rt"
+version = "0.5.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d1bd069de53442e7a320f525a6d4deb8bb0621ac7a55f7eccbc2b58b57f43d0"
+dependencies = [
+ "async-native-tls",
+ "async-std",
+ "native-tls",
+]
+
 [[package]]
 name = "standback"
 version = "0.2.17"
@@ -1817,6 +2259,16 @@ version = "0.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0"
 
+[[package]]
+name = "stringprep"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8ee348cb74b87454fff4b551cbf727025810a004f88aeacae7f85b87f4e9a1c1"
+dependencies = [
+ "unicode-bidi",
+ "unicode-normalization",
+]
+
 [[package]]
 name = "strsim"
 version = "0.8.0"
@@ -1858,6 +2310,20 @@ dependencies = [
  "unicode-xid",
 ]
 
+[[package]]
+name = "tempfile"
+version = "3.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "rand 0.8.4",
+ "redox_syscall 0.2.10",
+ "remove_dir_all",
+ "winapi 0.3.9",
+]
+
 [[package]]
 name = "textwrap"
 version = "0.11.0"
@@ -2049,7 +2515,7 @@ dependencies = [
  "idna",
  "lazy_static",
  "log",
- "rand",
+ "rand 0.7.3",
  "smallvec",
  "thiserror",
  "tokio",
@@ -2089,6 +2555,7 @@ dependencies = [
  "serde",
  "serde_json",
  "simple-logging",
+ "sqlx",
  "structopt",
  "thiserror",
  "url",
@@ -2143,6 +2610,12 @@ version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
 
+[[package]]
+name = "unicode_categories"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
+
 [[package]]
 name = "url"
 version = "2.2.2"
@@ -2180,7 +2653,7 @@ version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f29769400af8b264944b851c961a4a6930e76604f59b1fcd51246bab6a296c8c"
 dependencies = [
- "nom",
+ "nom 4.2.3",
  "proc-macro2",
  "quote",
  "syn",
@@ -2206,6 +2679,12 @@ dependencies = [
  "version_check 0.9.3",
 ]
 
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
 [[package]]
 name = "vec_map"
 version = "0.8.2"
@@ -2327,6 +2806,16 @@ dependencies = [
  "cc",
 ]
 
+[[package]]
+name = "whoami"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "524b58fa5a20a2fb3014dd6358b70e6579692a56ef6fce928834e488f42f65e8"
+dependencies = [
+ "wasm-bindgen",
+ "web-sys",
+]
+
 [[package]]
 name = "widestring"
 version = "0.4.3"
diff --git a/Cargo.toml b/Cargo.toml
index c538a529c2d89118b89e6e2702b8cd1b203f4e83..5f908aab2c50accf79b6613abd0dc33e956289b6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -22,4 +22,5 @@ chrono = { version = "^0.4.19", features = ["serde"] }
 serde_json = "1"
 log = "^0.4.14"
 url = "2.2.2"
-simple-logging = { version = "^2.0.2" }
\ No newline at end of file
+simple-logging = { version = "^2.0.2" }
+sqlx = { version = "0.5", features = [  "runtime-async-std-native-tls", "sqlite" ] }
\ No newline at end of file
diff --git a/src/config.rs b/src/config.rs
index 8e626c8e5cd52df214b5139f9c90792c340033c8..810ab5b74703cb37c17b32a52d0d9e49246482d0 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -5,44 +5,73 @@ use structopt::StructOpt;
 use crate::errors::TuserError;
 use crate::storages::AvailableStores;
 
+#[derive(StructOpt, Debug, Clone)]
+pub struct StorageOptions {
+    /// Tuser storage type.
+    #[structopt(long, short, default_value = "file_storage", env = "TUSER_STORAGE")]
+    pub storage: AvailableStores,
+
+    /// Tuser data directory
+    ///
+    /// This directory is used to store files
+    /// for all *file_storage storages.
+    #[structopt(
+    long,
+    default_value = "./data",
+    required_if("storage", "file_storage"),
+    required_if("storage", "sqlite_file_storage")
+    )]
+    pub data: PathBuf,
+
+    /// Path to SQLite file.
+    ///
+    /// This file is used to
+    /// store information about uploaded files.
+    #[structopt(
+    long,
+    default_value = "data/info.sqlite3",
+    required_if("storage", "sqlite_file_storage")
+    )]
+    pub sqlite_dsn: PathBuf,
+}
+
 #[derive(Debug, StructOpt, Clone)]
 #[structopt(name = "tuser", about = "Tus server implementation in Rust.")]
 pub struct TuserConf {
     /// Tuser host
-    #[structopt(short, long, default_value = "0.0.0.0")]
+    #[structopt(short, long, default_value = "0.0.0.0", env = "TUSER_HOST")]
     pub host: String,
 
     /// Tuser server port
-    #[structopt(short, long, default_value = "1081")]
+    #[structopt(short, long, default_value = "1081", env = "TUSER_PORT")]
     pub port: u16,
 
     /// Tuser base API url
-    #[structopt(long, default_value = "/files")]
+    #[structopt(long, default_value = "/files", env = "TUSER_URL")]
     pub url: String,
 
-    /// Tuser data directory
-    #[structopt(long, default_value = "./data")]
-    pub data: PathBuf,
-
     /// Enabled hooks for http events
-    #[structopt(long, default_value = "pre-create,post-finish")]
+    #[structopt(long, default_value = "pre-create,post-finish", env = "TUSER_HOOKS")]
     pub enabled_hooks: String,
 
     /// Tuser maximum log level
-    #[structopt(long, default_value = "INFO")]
+    #[structopt(long, default_value = "INFO", env = "TUSER_LOG_LEVEL")]
     pub log_level: log::LevelFilter,
 
-    /// Storage type
-    #[structopt(long, short, default_value = "file_storage")]
-    pub storage: AvailableStores,
-
     /// Number of actix workers default value = number of cpu cores.
-    #[structopt(long, short)]
+    #[structopt(long, short, env = "TUSER_WORKERS")]
     pub workers: Option<usize>,
 
     /// Enabled extensions for TUS protocol.
-    #[structopt(long, default_value = "creation,creation-with-upload")]
+    #[structopt(
+    long,
+    default_value = "creation,creation-with-upload",
+    env = "TUSER_EXTENSIONS"
+    )]
     pub extensions: String,
+
+    #[structopt(flatten)]
+    pub storage_opts: StorageOptions,
 }
 
 /// Enum of available Protocol Extensions
diff --git a/src/errors.rs b/src/errors.rs
index 3a70a22f99e631bea61689b3e3d4a82669b93724..60851b687f79b284261d3ae3d2a88bd5a621bc21 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -3,11 +3,10 @@ use std::io::{Error, ErrorKind};
 use actix_web::dev::HttpResponseBuilder;
 use actix_web::http::StatusCode;
 use actix_web::{HttpResponse, ResponseError};
-use thiserror::Error;
 
 pub type TuserResult<T> = Result<T, TuserError>;
 
-#[derive(Error, Debug)]
+#[derive(thiserror::Error, Debug)]
 pub enum TuserError {
     #[error("File with id {0} was not found")]
     FileNotFound(String),
@@ -19,6 +18,8 @@ pub enum TuserError {
     Unknown,
     #[error("Unable to serialize object")]
     UnableToSerialize(#[from] serde_json::Error),
+    #[error("Database error: {0}")]
+    DatabaseError(#[from] sqlx::Error),
     #[error("Unable to get file information")]
     UnableToReadInfo,
     #[error("Unable to write file {0}")]
diff --git a/src/main.rs b/src/main.rs
index bbfd9b5a2868870d0b7e6c45e7a2ed15016fe026..1ead5e97e8e8a2712d42360ec567c318ac115d31 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,5 @@
 use std::str::FromStr;
+use std::sync::Arc;
 
 use actix_web::http::Method;
 use actix_web::{
@@ -30,19 +31,21 @@ mod storages;
 /// This function may throw an error
 /// if the server can't be bound to the
 /// given address.
-pub fn create_server<S: Storage + 'static + Send>(
-    storage: S,
+pub fn create_server(
+    storage: Box<dyn Storage + Send + Sync>,
     app_conf: TuserConf,
 ) -> Result<Server, std::io::Error> {
     let host = app_conf.host.clone();
     let port = app_conf.port;
     let workers = app_conf.workers;
+    let storage_data: web::Data<Box<dyn Storage + Send + Sync>> =
+        web::Data::from(Arc::new(storage));
     let mut server = HttpServer::new(move || {
         App::new()
             .data(app_conf.clone())
-            .data(storage.clone())
+            .app_data(storage_data.clone())
             // Adds all routes.
-            .configure(protocol::setup::<S>(app_conf.clone()))
+            .configure(protocol::setup(app_conf.clone()))
             // Main middleware that appends TUS headers.
             .wrap(
                 middleware::DefaultHeaders::new()
@@ -81,7 +84,7 @@ async fn main() -> std::io::Result<()> {
     let app_conf = TuserConf::from_args();
     simple_logging::log_to_stderr(app_conf.log_level);
 
-    let storage = app_conf.storage.get_storage(&app_conf);
+    let mut storage = app_conf.storage_opts.storage.get(&app_conf);
     if let Err(err) = storage.prepare().await {
         error!("{}", err);
         return Err(err.into());
diff --git a/src/protocol/core/mod.rs b/src/protocol/core/mod.rs
index b2248f46f17bfd92e83814d8efb0e0947a462697..c76a19dd10582c87d9f213d1f7e34f97aa166b9e 100644
--- a/src/protocol/core/mod.rs
+++ b/src/protocol/core/mod.rs
@@ -1,6 +1,6 @@
 use actix_web::{guard, middleware, web};
 
-use crate::{Storage, TuserConf};
+use crate::TuserConf;
 
 mod routes;
 
@@ -12,10 +12,7 @@ mod routes;
 /// OPTIONS /api    - to get info about the app.
 /// HEAD /api/file  - to get info about the file.
 /// PATCH /api/file - to add bytes to file.
-pub fn add_extension<S: Storage + 'static + Send>(
-    web_app: &mut web::ServiceConfig,
-    app_conf: &TuserConf,
-) {
+pub fn add_extension(web_app: &mut web::ServiceConfig, app_conf: &TuserConf) {
     web_app
         .service(
             // PATCH /base/{file_id}
@@ -31,7 +28,7 @@ pub fn add_extension<S: Storage + 'static + Send>(
             web::resource(app_conf.file_url().as_str())
                 .name("core:write_bytes")
                 .guard(guard::Patch())
-                .to(routes::write_bytes::<S>),
+                .to(routes::write_bytes),
         )
         .service(
             // HEAD /base/{file_id}
@@ -41,6 +38,6 @@ pub fn add_extension<S: Storage + 'static + Send>(
                 .guard(guard::Head())
                 // Header to prevent the client and/or proxies from caching the response.
                 .wrap(middleware::DefaultHeaders::new().header("Cache-Control", "no-store"))
-                .to(routes::get_file_info::<S>),
+                .to(routes::get_file_info),
         );
 }
diff --git a/src/protocol/core/routes.rs b/src/protocol/core/routes.rs
index b43a63b967f6d101179857736d1d8d3f9b7ef218..87e769bbb080bdef5a3678114233595e0f61ad47 100644
--- a/src/protocol/core/routes.rs
+++ b/src/protocol/core/routes.rs
@@ -21,8 +21,8 @@ pub fn server_info(app_conf: web::Data<TuserConf>) -> HttpResponse {
         .body("")
 }
 
-pub async fn get_file_info<T: Storage>(
-    storage: web::Data<T>,
+pub async fn get_file_info(
+    storage: web::Data<Box<dyn Storage + Send + Sync>>,
     request: HttpRequest,
 ) -> actix_web::Result<HttpResponse> {
     let resp = if let Some(file_id) = request.match_info().get("file_id") {
@@ -37,10 +37,10 @@ pub async fn get_file_info<T: Storage>(
     Ok(resp)
 }
 
-pub async fn write_bytes<T: Storage>(
+pub async fn write_bytes(
     request: HttpRequest,
     bytes: Bytes,
-    storage: web::Data<T>,
+    storage: web::Data<Box<dyn Storage + Send + Sync>>,
 ) -> actix_web::Result<HttpResponse> {
     let content_type =
         request
diff --git a/src/protocol/creation/mod.rs b/src/protocol/creation/mod.rs
index 69214dc27555183200aae0bab7ff92c82302a40d..0b0245429b3672832b6a7f2d24cc66b05366ade0 100644
--- a/src/protocol/creation/mod.rs
+++ b/src/protocol/creation/mod.rs
@@ -1,6 +1,6 @@
 use actix_web::{guard, web};
 
-use crate::{Storage, TuserConf};
+use crate::TuserConf;
 
 mod routes;
 
@@ -8,16 +8,13 @@ mod routes;
 ///
 /// This extension allows you
 /// to create file before sending data.
-pub fn add_extension<S: Storage + 'static + Send>(
-    web_app: &mut web::ServiceConfig,
-    app_conf: &TuserConf,
-) {
+pub fn add_extension(web_app: &mut web::ServiceConfig, app_conf: &TuserConf) {
     web_app.service(
         // Post /base
         // URL for creating files.
         web::resource(app_conf.base_url().as_str())
             .name("creation:create_file")
             .guard(guard::Post())
-            .to(routes::create_file::<S>),
+            .to(routes::create_file),
     );
 }
diff --git a/src/protocol/creation/routes.rs b/src/protocol/creation/routes.rs
index d1177196b60e2c4c793282adcbf8e15c431b72f6..beb19b733cb364e557cb24d1d06ea53975a07379 100644
--- a/src/protocol/creation/routes.rs
+++ b/src/protocol/creation/routes.rs
@@ -4,8 +4,8 @@ use actix_web::{web, HttpRequest, HttpResponse};
 
 use crate::Storage;
 
-pub async fn create_file<T: Storage>(
-    storage: web::Data<T>,
+pub async fn create_file(
+    storage: web::Data<Box<dyn Storage + Send + Sync>>,
     request: HttpRequest,
 ) -> actix_web::Result<HttpResponse> {
     let length = request
diff --git a/src/protocol/creation_with_upload/mod.rs b/src/protocol/creation_with_upload/mod.rs
index a0b3707c169b7d6556bf283c548ee6050747f3a2..b02b0cf235280e2a2fb46b88a0c6e1f5b0cfb0e9 100644
--- a/src/protocol/creation_with_upload/mod.rs
+++ b/src/protocol/creation_with_upload/mod.rs
@@ -1,19 +1,16 @@
 use actix_web::{guard, web};
 
-use crate::{Storage, TuserConf};
+use crate::TuserConf;
 
 mod routes;
 
-pub fn add_extension<S: Storage + 'static + Send>(
-    web_app: &mut web::ServiceConfig,
-    app_conf: &TuserConf,
-) {
+pub fn add_extension(web_app: &mut web::ServiceConfig, app_conf: &TuserConf) {
     web_app.service(
         // Post /base
         // URL for creating files.
         web::resource(app_conf.base_url().as_str())
             .name("creation-with-upload:create_file")
             .guard(guard::Post())
-            .to(routes::create_file::<S>),
+            .to(routes::create_file),
     );
 }
diff --git a/src/protocol/creation_with_upload/routes.rs b/src/protocol/creation_with_upload/routes.rs
index c3b38a00a7e04879ad439a20804187dee3581c8b..7b6cb95e36852b39b2f9b17ce2e1d7ebec2d31da 100644
--- a/src/protocol/creation_with_upload/routes.rs
+++ b/src/protocol/creation_with_upload/routes.rs
@@ -8,11 +8,11 @@ use crate::Storage;
 /// Creates files with initial bytes.
 ///
 /// This function is similar to
-/// creation:create_file,
+/// `creation:create_file`,
 /// except that it can write bytes
 /// right after it created a data file.
-pub async fn create_file<T: Storage>(
-    storage: web::Data<T>,
+pub async fn create_file(
+    storage: web::Data<Box<dyn Storage + Send + Sync>>,
     request: HttpRequest,
     bytes: Bytes,
 ) -> actix_web::Result<HttpResponse> {
diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs
index b41c1475af3f43fa1e5f8ec852b3971b04ab31cf..ae3cd98d6729c610683c89e462c3fa675e4a45c3 100644
--- a/src/protocol/mod.rs
+++ b/src/protocol/mod.rs
@@ -1,7 +1,7 @@
 use actix_web::web;
 
 use crate::config::ProtocolExtensions;
-use crate::{Storage, TuserConf};
+use crate::TuserConf;
 
 mod core;
 mod creation;
@@ -12,21 +12,19 @@ mod termination;
 ///
 /// This function resolves all protocol extensions
 /// provided by CLI into services and adds it to the application.
-pub fn setup<S: Storage + 'static + Send>(
-    app_conf: TuserConf,
-) -> Box<dyn Fn(&mut web::ServiceConfig)> {
+pub fn setup(app_conf: TuserConf) -> Box<dyn Fn(&mut web::ServiceConfig)> {
     Box::new(move |web_app| {
         for extension in app_conf.extensions_vec() {
             match extension {
-                ProtocolExtensions::Creation => creation::add_extension::<S>(web_app, &app_conf),
+                ProtocolExtensions::Creation => creation::add_extension(web_app, &app_conf),
                 ProtocolExtensions::CreationWithUpload => {
-                    creation_with_upload::add_extension::<S>(web_app, &app_conf);
+                    creation_with_upload::add_extension(web_app, &app_conf);
                 }
                 ProtocolExtensions::Termination => {
-                    termination::add_extension::<S>(web_app, &app_conf);
+                    termination::add_extension(web_app, &app_conf);
                 }
             }
         }
-        core::add_extension::<S>(web_app, &app_conf);
+        core::add_extension(web_app, &app_conf);
     })
 }
diff --git a/src/protocol/termination/mod.rs b/src/protocol/termination/mod.rs
index 7ed341d05ad5a48c9b28866d81199ae171a42545..ae8c62cf57540cd4faf9cfc82761486246800b2f 100644
--- a/src/protocol/termination/mod.rs
+++ b/src/protocol/termination/mod.rs
@@ -1,6 +1,6 @@
 use actix_web::{guard, web};
 
-use crate::{Storage, TuserConf};
+use crate::TuserConf;
 
 mod routes;
 
@@ -8,15 +8,12 @@ mod routes;
 ///
 /// This extension allows you
 /// to terminate file upload.
-pub fn add_extension<S: Storage + 'static + Send>(
-    web_app: &mut web::ServiceConfig,
-    app_conf: &TuserConf,
-) {
+pub fn add_extension(web_app: &mut web::ServiceConfig, app_conf: &TuserConf) {
     web_app.service(
         // DELETE /base/file
         web::resource(app_conf.file_url().as_str())
             .name("termination:terminate")
             .guard(guard::Delete())
-            .to(routes::terminate::<S>),
+            .to(routes::terminate),
     );
 }
diff --git a/src/protocol/termination/routes.rs b/src/protocol/termination/routes.rs
index 0aa971ce962e985810e74013579067879d74b2b7..4125a20cbf88f23297b11e927d45cdb28b979257 100644
--- a/src/protocol/termination/routes.rs
+++ b/src/protocol/termination/routes.rs
@@ -9,8 +9,8 @@ use crate::Storage;
 ///
 /// This method will remove all
 /// files by id.
-pub async fn terminate<S: Storage>(
-    storage: web::Data<S>,
+pub async fn terminate(
+    storage: web::Data<Box<dyn Storage + Send + Sync>>,
     request: HttpRequest,
 ) -> TuserResult<HttpResponse> {
     let file_id_opt = request.match_info().get("file_id").map(String::from);
diff --git a/src/storages/file_storage.rs b/src/storages/file_storage.rs
index 1f6abeb63b2a8c7626e77c4c6ce4e303079a81ab..433033f687ca5bdf72e5c7cd3c8eaeac45ff0894 100644
--- a/src/storages/file_storage.rs
+++ b/src/storages/file_storage.rs
@@ -2,7 +2,7 @@ use std::collections::HashMap;
 use std::path::PathBuf;
 
 use actix_files::NamedFile;
-use async_std::fs::{DirBuilder, OpenOptions, read_to_string, remove_file};
+use async_std::fs::{read_to_string, remove_file, DirBuilder, OpenOptions};
 use async_std::prelude::*;
 use async_trait::async_trait;
 use log::error;
@@ -23,20 +23,23 @@ impl FileStorage {
     }
 
     pub fn info_file_path(&self, file_id: &str) -> PathBuf {
-        self.app_conf.data.join(format!("{}.info", file_id))
+        self.app_conf
+            .storage_opts
+            .data
+            .join(format!("{}.info", file_id))
     }
 
     pub fn data_file_path(&self, file_id: &str) -> PathBuf {
-        self.app_conf.data.join(file_id.to_string())
+        self.app_conf.storage_opts.data.join(file_id.to_string())
     }
 }
 
 #[async_trait]
 impl Storage for FileStorage {
-    async fn prepare(&self) -> TuserResult<()> {
-        if !self.app_conf.data.exists() {
+    async fn prepare(&mut self) -> TuserResult<()> {
+        if !self.app_conf.storage_opts.data.exists() {
             DirBuilder::new()
-                .create(self.app_conf.data.as_path())
+                .create(self.app_conf.storage_opts.data.as_path())
                 .await
                 .map_err(|err| TuserError::UnableToPrepareStorage(err.to_string()))?;
         }
diff --git a/src/storages/mod.rs b/src/storages/mod.rs
index 613d77f47a5b07d21f11729cd7d609ff317fbbc9..afeb42ace6b409b1d047a9b271c836a7cd019e09 100644
--- a/src/storages/mod.rs
+++ b/src/storages/mod.rs
@@ -3,21 +3,25 @@ use std::str::FromStr;
 
 use actix_files::NamedFile;
 use async_trait::async_trait;
-use chrono::serde::ts_seconds;
 use chrono::{DateTime, Utc};
+use chrono::serde::ts_seconds;
 use derive_more::{Display, From};
 use serde::{Deserialize, Serialize};
+use sqlx::FromRow;
 
 use crate::errors::TuserResult;
 use crate::TuserConf;
 
 pub mod file_storage;
+pub mod sqlite_file_storage;
 
 /// Enum of available Storage implementations.
 #[derive(PartialEq, From, Display, Clone, Debug)]
 pub enum AvailableStores {
     #[display(fmt = "FileStorage")]
     FileStorage,
+    #[display(fmt = "SqliteFileStorage")]
+    SqliteFileStorage,
 }
 
 impl FromStr for AvailableStores {
@@ -31,6 +35,7 @@ impl FromStr for AvailableStores {
     fn from_str(input: &str) -> Result<AvailableStores, Self::Err> {
         match input {
             "file_storage" => Ok(AvailableStores::FileStorage),
+            "sqlite_file_storage" => Ok(AvailableStores::SqliteFileStorage),
             _ => Err(String::from("Unknown storage type")),
         }
     }
@@ -42,15 +47,19 @@ impl AvailableStores {
     /// # Params
     /// `config` - Tuser configuration.
     ///
-    #[allow(clippy::unused_self)]
-    pub fn get_storage(&self, config: &TuserConf) -> impl Storage {
-        file_storage::FileStorage::new(config.clone())
+    pub fn get(&self, config: &TuserConf) -> Box<dyn Storage + Send + Sync> {
+        match self {
+            Self::FileStorage => Box::new(file_storage::FileStorage::new(config.clone())),
+            Self::SqliteFileStorage => {
+                Box::new(sqlite_file_storage::SQLiteFileStorage::new(config.clone()))
+            }
+        }
     }
 }
 
 /// Information about file.
 /// It has everything about stored file.
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, FromRow)]
 pub struct FileInfo {
     pub id: String,
     pub offset: usize,
@@ -103,13 +112,13 @@ impl FileInfo {
 }
 
 #[async_trait]
-pub trait Storage: Clone {
+pub trait Storage {
     /// Prepare storage before starting up server.
     ///
     /// Function to check if configuration is correct
     /// and prepare storage E.G. create connection pool,
     /// or directory for files.
-    async fn prepare(&self) -> TuserResult<()>;
+    async fn prepare(&mut self) -> TuserResult<()>;
 
     /// Get file information.
     ///
diff --git a/src/storages/sqlite_file_storage.rs b/src/storages/sqlite_file_storage.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d0039dc514067fa1ab609b216d054409f534b9be
--- /dev/null
+++ b/src/storages/sqlite_file_storage.rs
@@ -0,0 +1,107 @@
+use std::collections::HashMap;
+
+use actix_files::NamedFile;
+use async_std::fs::{DirBuilder, File};
+use async_trait::async_trait;
+use log::error;
+use sqlx::sqlite::SqlitePoolOptions;
+use sqlx::SqlitePool;
+use thiserror::private::PathAsDisplay;
+
+use crate::errors::{TuserError, TuserResult};
+use crate::storages::{FileInfo, Storage};
+use crate::TuserConf;
+
+#[derive(Clone)]
+pub struct SQLiteFileStorage {
+    app_conf: TuserConf,
+    pool: Option<SqlitePool>,
+}
+
+impl SQLiteFileStorage {
+    pub fn new(app_conf: TuserConf) -> SQLiteFileStorage {
+        SQLiteFileStorage {
+            app_conf,
+            pool: None,
+        }
+    }
+
+    #[allow(dead_code)]
+    pub fn get_pool(&self) -> TuserResult<&SqlitePool> {
+        if let Some(pool) = &self.pool {
+            Ok(pool)
+        } else {
+            error!("Pool doesn't exist.");
+            Err(TuserError::Unknown)
+        }
+    }
+}
+
+#[async_trait]
+impl Storage for SQLiteFileStorage {
+    async fn prepare(&mut self) -> TuserResult<()> {
+        if !self.app_conf.storage_opts.data.exists() {
+            DirBuilder::new()
+                .create(self.app_conf.storage_opts.data.as_path())
+                .await
+                .map_err(|err| TuserError::UnableToPrepareStorage(err.to_string()))?;
+        }
+        if !self.app_conf.storage_opts.sqlite_dsn.exists() {
+            File::create(self.app_conf.storage_opts.sqlite_dsn.clone()).await.map_err(|err| {
+                TuserError::UnableToPrepareStorage(err.to_string())
+            })?;
+        }
+        let pool = SqlitePoolOptions::new()
+            .max_connections(10)
+            .connect(format!("sqlite://{}", self.app_conf.storage_opts.sqlite_dsn.as_display().to_string()).as_str())
+            .await
+            .map_err(TuserError::from)?;
+        sqlx::query(
+            "CREATE TABLE IF NOT EXISTS \
+                fileinfo(\
+                    id VARCHAR(40) PRIMARY KEY, \
+                    offset UNSIGNED BIG INT NOT NULL DEFAULT 0, \
+                    length UNSIGNED BIG INT, \
+                    path TEXT, \
+                    created_at DATETIME, \
+                    deferred_size BOOLEAN, \
+                    metadata TEXT\
+               );",
+        ).execute(&pool).await?;
+        self.pool = Some(pool);
+        Ok(())
+    }
+
+    async fn get_file_info(&self, _file_id: &str) -> TuserResult<FileInfo> {
+        todo!()
+    }
+
+    async fn set_file_info(&self, _file_info: &FileInfo) -> TuserResult<()> {
+        todo!()
+    }
+
+    async fn get_contents(&self, _file_id: &str) -> TuserResult<NamedFile> {
+        todo!()
+    }
+
+    async fn add_bytes(
+        &self,
+        _file_id: &str,
+        _request_offset: usize,
+        _bytes: &[u8],
+    ) -> TuserResult<usize> {
+        todo!()
+    }
+
+    async fn create_file(
+        &self,
+        _file_size: Option<usize>,
+        _metadata: Option<HashMap<String, String>>,
+    ) -> TuserResult<String> {
+        todo!()
+    }
+
+    async fn remove_file(&self, _file_id: &str) -> TuserResult<()> {
+        todo!()
+    }
+}