diff --git a/src/errors.rs b/src/errors.rs
index af844fff668818d7c6ef573f3890888d85c73260..19be4062cb8e175be17b2094c0b2c237626bed2c 100644
--- a/src/errors.rs
+++ b/src/errors.rs
@@ -2,6 +2,7 @@ use std::io::{Error, ErrorKind};
 
 use actix_web::http::StatusCode;
 use actix_web::{HttpResponse, HttpResponseBuilder, ResponseError};
+use log::error;
 
 pub type RustusResult<T> = Result<T, RustusError>;
 
@@ -69,6 +70,7 @@ impl From<RustusError> for Error {
 /// Trait to convert errors to http-responses.
 impl ResponseError for RustusError {
     fn error_response(&self) -> HttpResponse {
+        error!("{}", self);
         HttpResponseBuilder::new(self.status_code())
             .insert_header(("Content-Type", "text/html; charset=utf-8"))
             .body(format!("{}", self))
diff --git a/src/info_storages/models/file_info.rs b/src/info_storages/models/file_info.rs
index bcab553c9a387a80313d6a9b07949587848a1f99..c593df4ecf595d3e0be5b73a8a8e3ecd512ad8f7 100644
--- a/src/info_storages/models/file_info.rs
+++ b/src/info_storages/models/file_info.rs
@@ -15,6 +15,7 @@ pub struct FileInfo {
     #[serde(with = "ts_seconds")]
     pub created_at: DateTime<Utc>,
     pub deferred_size: bool,
+    pub storage: String,
     pub metadata: HashMap<String, String>,
 }
 
@@ -32,6 +33,7 @@ impl FileInfo {
         file_id: &str,
         length: Option<usize>,
         path: Option<String>,
+        storage: String,
         initial_metadata: Option<HashMap<String, String>>,
     ) -> FileInfo {
         let id = String::from(file_id);
@@ -49,6 +51,7 @@ impl FileInfo {
             id,
             path,
             length,
+            storage,
             metadata,
             deferred_size,
             offset: 0,
diff --git a/src/main.rs b/src/main.rs
index fdddec43820a7e1a556674ba7b32f226711a1f74..80a3b6123f817a7e91ce3aff296596f445c6208a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -11,6 +11,7 @@ use fern::Dispatch;
 use log::LevelFilter;
 
 use crate::errors::RustusResult;
+use crate::info_storages::InfoStorage;
 use crate::notifiers::models::notification_manager::NotificationManager;
 use config::RustusConf;
 
@@ -65,6 +66,7 @@ fn greeting(app_conf: &RustusConf) {
 /// given address.
 pub fn create_server(
     storage: Box<dyn Storage + Send + Sync>,
+    info_storage: Box<dyn InfoStorage + Send + Sync>,
     app_conf: RustusConf,
     notification_manager: NotificationManager,
 ) -> Result<Server, std::io::Error> {
@@ -72,6 +74,8 @@ pub fn create_server(
     let port = app_conf.port;
     let workers = app_conf.workers;
     let app_conf_data = web::Data::new(app_conf.clone());
+    let info_storage_data: web::Data<Box<dyn InfoStorage + Send + Sync>> =
+        web::Data::from(Arc::new(info_storage));
     let storage_data: web::Data<Box<dyn Storage + Send + Sync>> =
         web::Data::from(Arc::new(storage));
     let manager_data: web::Data<Box<NotificationManager>> =
@@ -81,6 +85,7 @@ pub fn create_server(
             .app_data(app_conf_data.clone())
             .app_data(storage_data.clone())
             .app_data(manager_data.clone())
+            .app_data(info_storage_data.clone())
             // Adds all routes.
             .configure(protocol::setup(app_conf.clone()))
             // Main middleware that appends TUS headers.
@@ -163,7 +168,7 @@ async fn main() -> std::io::Result<()> {
     info_storage.prepare().await?;
 
     // Creating file storage.
-    let mut storage = app_conf.storage_opts.storage.get(&app_conf, info_storage);
+    let mut storage = app_conf.storage_opts.storage.get(&app_conf);
     // Preparing it.
     storage.prepare().await?;
 
@@ -171,6 +176,6 @@ async fn main() -> std::io::Result<()> {
     let notification_manager = NotificationManager::new(&app_conf).await?;
 
     // Creating actual server and running it.
-    let server = create_server(storage, app_conf, notification_manager)?;
+    let server = create_server(storage, info_storage, app_conf, notification_manager)?;
     server.await
 }
diff --git a/src/notifiers/models/message_format.rs b/src/notifiers/models/message_format.rs
index 578c74cd5fec5194f28fbef2b2790f1c785eab1b..6c9fb9c2ffa0508b4ae0889ef5649ec76a6dcafa 100644
--- a/src/notifiers/models/message_format.rs
+++ b/src/notifiers/models/message_format.rs
@@ -68,7 +68,7 @@ impl From<FileInfo> for TusdFileInfo {
             partial_uploads: None,
             metadata: file_info.metadata,
             storage: TusdStorageInfo {
-                storage_type: "filestore".into(),
+                storage_type: file_info.storage,
                 path: file_info.path,
             },
         }
diff --git a/src/protocol/core/routes.rs b/src/protocol/core/routes.rs
index 7ba5919abe84b1595ac7c49de3ad2d2c0189692c..f9f282db5896bcede50652a7e037a8b785bffc73 100644
--- a/src/protocol/core/routes.rs
+++ b/src/protocol/core/routes.rs
@@ -1,9 +1,10 @@
-use actix_web::{http::StatusCode, web, web::Bytes, HttpRequest, HttpResponse};
+use actix_web::{web, web::Bytes, HttpRequest, HttpResponse};
 
+use crate::errors::RustusError;
 use crate::notifiers::Hook;
 use crate::protocol::extensions::Extensions;
 use crate::utils::headers::{check_header, parse_header};
-use crate::{NotificationManager, RustusConf, Storage};
+use crate::{InfoStorage, NotificationManager, RustusConf, Storage};
 
 #[allow(clippy::needless_pass_by_value)]
 pub fn server_info(app_conf: web::Data<RustusConf>) -> HttpResponse {
@@ -19,27 +20,34 @@ pub fn server_info(app_conf: web::Data<RustusConf>) -> HttpResponse {
 }
 
 pub async fn get_file_info(
+    info_storage: web::Data<Box<dyn InfoStorage + Send + Sync>>,
     storage: web::Data<Box<dyn Storage + Send + Sync>>,
     request: HttpRequest,
 ) -> actix_web::Result<HttpResponse> {
+    // Getting file id from URL.
+    if request.match_info().get("file_id").is_none() {
+        return Ok(HttpResponse::NotFound().body(""));
+    }
+    let file_id = request.match_info().get("file_id").unwrap();
+
+    // Getting file info from info_storage.
+    let file_info = info_storage.get_info(file_id).await?;
+    if file_info.storage != storage.to_string() {
+        return Ok(HttpResponse::NotFound().body(""));
+    }
     let mut builder = HttpResponse::Ok();
-    if let Some(file_id) = request.match_info().get("file_id") {
-        let file_info = storage.get_file_info(file_id).await?;
-        builder
-            .insert_header(("Upload-Offset", file_info.offset.to_string()))
-            .insert_header(("Content-Length", file_info.offset.to_string()));
-        // Upload length is known.
-        if let Some(upload_len) = file_info.length {
-            builder.insert_header(("Upload-Length", upload_len.to_string()));
-        } else {
-            builder.insert_header(("Upload-Defer-Length", "1"));
-        }
-        if let Some(meta) = file_info.get_metadata_string() {
-            builder.insert_header(("Upload-Metadata", meta));
-        }
+    builder
+        .insert_header(("Upload-Offset", file_info.offset.to_string()))
+        .insert_header(("Content-Length", file_info.offset.to_string()));
+    // Upload length is known.
+    if let Some(upload_len) = file_info.length {
+        builder.insert_header(("Upload-Length", upload_len.to_string()));
     } else {
-        builder.status(StatusCode::NOT_FOUND);
-    };
+        builder.insert_header(("Upload-Defer-Length", "1"));
+    }
+    if let Some(meta) = file_info.get_metadata_string() {
+        builder.insert_header(("Upload-Metadata", meta));
+    }
     Ok(builder.body(""))
 }
 
@@ -47,18 +55,25 @@ pub async fn write_bytes(
     request: HttpRequest,
     bytes: Bytes,
     storage: web::Data<Box<dyn Storage + Send + Sync>>,
+    info_storage: web::Data<Box<dyn InfoStorage + Send + Sync>>,
     notification_manager: web::Data<Box<NotificationManager>>,
     app_conf: web::Data<RustusConf>,
 ) -> actix_web::Result<HttpResponse> {
+    // Checking if request has required headers.
     if !check_header(&request, "Content-Type", "application/offset+octet-stream") {
         return Ok(HttpResponse::UnsupportedMediaType().body(""));
     }
-    let offset = parse_header(&request, "Upload-Offset");
+    // Getting current offset.
+    let offset: Option<usize> = parse_header(&request, "Upload-Offset");
 
     if offset.is_none() {
         return Ok(HttpResponse::UnsupportedMediaType().body(""));
     }
 
+    if request.match_info().get("file_id").is_none() {
+        return Ok(HttpResponse::NotFound().body(""));
+    }
+
     // New upload length.
     // Parses header `Upload-Length` only if the creation-defer-length extension is enabled.
     let updated_len = if app_conf
@@ -70,30 +85,69 @@ pub async fn write_bytes(
         None
     };
 
-    if let Some(file_id) = request.match_info().get("file_id") {
-        let file_info = storage
-            .add_bytes(file_id, offset.unwrap(), updated_len, bytes.as_ref())
-            .await?;
-        let mut hook = Hook::PostReceive;
-        if file_info.length == Some(file_info.offset) {
-            hook = Hook::PostFinish;
+    let file_id = request.match_info().get("file_id").unwrap();
+    // Getting file info.
+    let mut file_info = info_storage.get_info(file_id).await?;
+
+    // Checking if file was stored in the same storage.
+    if file_info.storage != storage.to_string() {
+        return Ok(HttpResponse::NotFound().body(""));
+    }
+    // Checking if offset from request is the same as the real offset.
+    if offset.unwrap() != file_info.offset {
+        return Ok(HttpResponse::Conflict().body(""));
+    }
+
+    // If someone want to update file length.
+    // This required by Upload-Defer-Length extension.
+    if let Some(new_len) = updated_len {
+        // Whoop, someone gave us total file length
+        // less that he had already uploaded.
+        if new_len < file_info.offset {
+            return Err(RustusError::WrongOffset.into());
         }
-        if app_conf.hook_is_active(hook) {
-            let message = app_conf
-                .notification_opts
-                .hooks_format
-                .format(&request, &file_info)?;
-            let headers = request.headers().clone();
-            tokio::spawn(async move {
-                notification_manager
-                    .send_message(message, hook, &headers)
-                    .await
-            });
+        // We already know the exact size of a file.
+        // Someone want to update it.
+        // Anyway, it's not allowed, heh.
+        if file_info.length.is_some() {
+            return Err(RustusError::SizeAlreadyKnown.into());
         }
-        Ok(HttpResponse::NoContent()
-            .insert_header(("Upload-Offset", file_info.offset.to_string()))
-            .body(""))
-    } else {
-        Ok(HttpResponse::NotFound().body(""))
+
+        // All checks are ok. Now our file will have exact size.
+        file_info.deferred_size = false;
+        file_info.length = Some(new_len);
+    }
+
+    // Checking if the size of the upload is already equals
+    // to calculated offset. It means that all bytes were already written.
+    if Some(file_info.offset) == file_info.length {
+        return Err(RustusError::FrozenFile.into());
+    }
+
+    // Appending bytes to file.
+    storage.add_bytes(&file_info, bytes.as_ref()).await?;
+    // Updating offset.
+    file_info.offset += bytes.len();
+    // Saving info to info storage.
+    info_storage.set_info(&file_info, false).await?;
+
+    let mut hook = Hook::PostReceive;
+    if file_info.length == Some(file_info.offset) {
+        hook = Hook::PostFinish;
+    }
+    if app_conf.hook_is_active(hook) {
+        let message = app_conf
+            .notification_opts
+            .hooks_format
+            .format(&request, &file_info)?;
+        let headers = request.headers().clone();
+        tokio::spawn(async move {
+            notification_manager
+                .send_message(message, hook, &headers)
+                .await
+        });
     }
+    Ok(HttpResponse::NoContent()
+        .insert_header(("Upload-Offset", file_info.offset.to_string()))
+        .body(""))
 }
diff --git a/src/protocol/creation/routes.rs b/src/protocol/creation/routes.rs
index b24ca73503b53b006860bce45ea9ae0d46130efd..61bbdca8f54e698b888d1683da499d7c82075176 100644
--- a/src/protocol/creation/routes.rs
+++ b/src/protocol/creation/routes.rs
@@ -7,7 +7,7 @@ use crate::info_storages::FileInfo;
 use crate::notifiers::Hook;
 use crate::protocol::extensions::Extensions;
 use crate::utils::headers::{check_header, parse_header};
-use crate::{NotificationManager, RustusConf, Storage};
+use crate::{InfoStorage, NotificationManager, RustusConf, Storage};
 
 /// Get metadata info from request.
 ///
@@ -49,8 +49,17 @@ fn get_metadata(request: &HttpRequest) -> Option<HashMap<String, String>> {
         })
 }
 
+/// Create file.
+///
+/// This method allows you to create file to start uploading.
+///
+/// This method supports defer-length if
+/// you don't know actual file length and
+/// you can upload first bytes if creation-with-upload
+/// extension is enabled.
 pub async fn create_file(
     storage: web::Data<Box<dyn Storage + Send + Sync>>,
+    info_storage: web::Data<Box<dyn InfoStorage + Send + Sync>>,
     notification_manager: web::Data<Box<NotificationManager>>,
     app_conf: web::Data<RustusConf>,
     request: HttpRequest,
@@ -75,20 +84,28 @@ pub async fn create_file(
 
     let meta = get_metadata(&request);
 
+    let file_id = uuid::Uuid::new_v4().to_string();
+    let mut file_info = FileInfo::new(
+        file_id.as_str(),
+        length,
+        None,
+        storage.to_string(),
+        meta.clone(),
+    );
+
     if app_conf.hook_is_active(Hook::PreCreate) {
-        let initial_file_info = FileInfo::new("", length, None, meta.clone());
         let message = app_conf
             .notification_opts
             .hooks_format
-            .format(&request, &initial_file_info)?;
+            .format(&request, &file_info)?;
         let headers = request.headers();
         notification_manager
             .send_message(message, Hook::PreCreate, headers)
             .await?;
     }
 
-    // Create file and get the id.
-    let mut file_info = storage.create_file(length, meta).await?;
+    // Create file and get the it's path.
+    file_info.path = Some(storage.create_file(&file_info).await?);
 
     // Create upload URL for this file.
     let upload_url = request.url_for("core:write_bytes", &[file_info.id.clone()])?;
@@ -102,11 +119,12 @@ pub async fn create_file(
             return Ok(HttpResponse::BadRequest().body(""));
         }
         // Writing first bytes.
-        file_info = storage
-            .add_bytes(file_info.id.as_str(), 0, None, bytes.as_ref())
-            .await?;
+        storage.add_bytes(&file_info, bytes.as_ref()).await?;
+        file_info.offset += bytes.len();
     }
 
+    info_storage.set_info(&file_info, true).await?;
+
     if app_conf.hook_is_active(Hook::PostCreate) {
         let message = app_conf
             .notification_opts
diff --git a/src/protocol/getting/routes.rs b/src/protocol/getting/routes.rs
index fdd918d7dc9ddad17c42c2e155209299cacbba1e..44186c81c6bbb64727aaad6a82444edeb550c741 100644
--- a/src/protocol/getting/routes.rs
+++ b/src/protocol/getting/routes.rs
@@ -1,15 +1,23 @@
 use actix_web::{web, HttpRequest, Responder};
 
 use crate::errors::RustusError;
-use crate::Storage;
+use crate::{InfoStorage, Storage};
 
+/// Retrieve actual file.
+///
+/// This method allows you to download files directly from storage.
 pub async fn get_file(
     request: HttpRequest,
     storage: web::Data<Box<dyn Storage + Send + Sync>>,
+    info_storage: web::Data<Box<dyn InfoStorage + Send + Sync>>,
 ) -> impl Responder {
     let file_id_opt = request.match_info().get("file_id").map(String::from);
     if let Some(file_id) = file_id_opt {
-        storage.get_contents(file_id.as_str()).await
+        let file_info = info_storage.get_info(file_id.as_str()).await?;
+        if file_info.storage != storage.to_string() {
+            return Err(RustusError::FileNotFound);
+        }
+        storage.get_contents(&file_info).await
     } else {
         Err(RustusError::FileNotFound)
     }
diff --git a/src/protocol/termination/routes.rs b/src/protocol/termination/routes.rs
index 696feb2d44a824e6bb04d18512ea92a8d2884f6f..16d809406a955c404a8ae0d19383b5b1fb171114 100644
--- a/src/protocol/termination/routes.rs
+++ b/src/protocol/termination/routes.rs
@@ -2,21 +2,27 @@ use actix_web::{web, HttpRequest, HttpResponse};
 
 use crate::errors::RustusResult;
 use crate::notifiers::Hook;
-use crate::{NotificationManager, RustusConf, Storage};
+use crate::{InfoStorage, NotificationManager, RustusConf, Storage};
 
 /// Terminate uploading.
 ///
-/// This method will remove all
-/// files by id.
+/// This method will remove all data by id.
+/// It removes info and actual data.
 pub async fn terminate(
     storage: web::Data<Box<dyn Storage + Send + Sync>>,
+    info_storage: web::Data<Box<dyn InfoStorage + Send + Sync>>,
     request: HttpRequest,
     notification_manager: web::Data<Box<NotificationManager>>,
     app_conf: web::Data<RustusConf>,
 ) -> RustusResult<HttpResponse> {
     let file_id_opt = request.match_info().get("file_id").map(String::from);
     if let Some(file_id) = file_id_opt {
-        let file_info = storage.remove_file(file_id.as_str()).await?;
+        let file_info = info_storage.get_info(file_id.as_str()).await?;
+        if file_info.storage != storage.to_string() {
+            return Ok(HttpResponse::NotFound().body(""));
+        }
+        info_storage.remove_info(file_id.as_str()).await?;
+        storage.remove_file(&file_info).await?;
         if app_conf.hook_is_active(Hook::PostTerminate) {
             let message = app_conf
                 .notification_opts
diff --git a/src/storages/file_storage.rs b/src/storages/file_storage.rs
index b6b7419cdb6223fd0d07e1304ae85a2fa20b0958..8d8c989255b689b8d32f8ada2f2599511e82d599 100644
--- a/src/storages/file_storage.rs
+++ b/src/storages/file_storage.rs
@@ -1,4 +1,3 @@
-use std::collections::HashMap;
 use std::path::PathBuf;
 
 use actix_files::NamedFile;
@@ -6,27 +5,22 @@ use async_std::fs::{remove_file, DirBuilder, OpenOptions};
 use async_std::prelude::*;
 use async_trait::async_trait;
 use log::error;
-use uuid::Uuid;
 
 use crate::errors::{RustusError, RustusResult};
-use crate::info_storages::{FileInfo, InfoStorage};
+use crate::info_storages::FileInfo;
 use crate::storages::Storage;
 use crate::RustusConf;
+use derive_more::Display;
 
+#[derive(Display)]
+#[display(fmt = "file_storage")]
 pub struct FileStorage {
     app_conf: RustusConf,
-    info_storage: Box<dyn InfoStorage + Send + Sync>,
 }
 
 impl FileStorage {
-    pub fn new(
-        app_conf: RustusConf,
-        info_storage: Box<dyn InfoStorage + Send + Sync>,
-    ) -> FileStorage {
-        FileStorage {
-            app_conf,
-            info_storage,
-        }
+    pub fn new(app_conf: RustusConf) -> FileStorage {
+        FileStorage { app_conf }
     }
 
     pub async fn data_file_path(&self, file_id: &str) -> RustusResult<PathBuf> {
@@ -68,17 +62,11 @@ impl Storage for FileStorage {
         Ok(())
     }
 
-    async fn get_file_info(&self, file_id: &str) -> RustusResult<FileInfo> {
-        // I don't think comments are convenient here.
-        self.info_storage.get_info(file_id).await
-    }
-
-    async fn get_contents(&self, file_id: &str) -> RustusResult<NamedFile> {
-        let info = self.info_storage.get_info(file_id).await?;
-        if info.path.is_none() {
+    async fn get_contents(&self, file_info: &FileInfo) -> RustusResult<NamedFile> {
+        if file_info.path.is_none() {
             return Err(RustusError::FileNotFound);
         }
-        NamedFile::open_async(info.path.unwrap().as_str())
+        NamedFile::open_async(file_info.path.clone().unwrap().as_str())
             .await
             .map_err(|err| {
                 error!("{:?}", err);
@@ -86,47 +74,12 @@ impl Storage for FileStorage {
             })
     }
 
-    async fn add_bytes(
-        &self,
-        file_id: &str,
-        request_offset: usize,
-        updated_length: Option<usize>,
-        bytes: &[u8],
-    ) -> RustusResult<FileInfo> {
-        let mut info = self.info_storage.get_info(file_id).await?;
-        // Checking that provided offset is equal to offset provided by request.
-        if info.offset != request_offset {
-            return Err(RustusError::WrongOffset);
-        }
+    async fn add_bytes(&self, info: &FileInfo, bytes: &[u8]) -> RustusResult<()> {
         // In normal situation this `if` statement is not
         // gonna be called, but what if it is ...
         if info.path.is_none() {
             return Err(RustusError::FileNotFound);
         }
-        // This thing is only applicable in case
-        // if tus-extension `creation-defer-length` is enabled.
-        if let Some(new_len) = updated_length {
-            // Whoop, someone gave us total file length
-            // less that he had already uploaded.
-            if new_len < info.offset {
-                return Err(RustusError::WrongOffset);
-            }
-            // We already know the exact size of a file.
-            // Someone want to update it.
-            // Anyway, it's not allowed, heh.
-            if info.length.is_some() {
-                return Err(RustusError::SizeAlreadyKnown);
-            }
-
-            // All checks are ok. Now our file will have exact size.
-            info.deferred_size = false;
-            info.length = Some(new_len);
-        }
-        // Checking if the size of the upload is already equals
-        // to calculated offset. It means that all bytes were already written.
-        if Some(info.offset) == info.length {
-            return Err(RustusError::FrozenFile);
-        }
         // Opening file in w+a mode.
         // It means that we're going to append some
         // bytes to the end of a file.
@@ -146,23 +99,12 @@ impl Storage for FileStorage {
         })?;
         file.sync_data().await?;
         // Updating information about file.
-        info.offset += bytes.len();
-        self.info_storage.set_info(&info, false).await?;
-        Ok(info)
+        Ok(())
     }
 
-    async fn create_file(
-        &self,
-        file_size: Option<usize>,
-        metadata: Option<HashMap<String, String>>,
-    ) -> RustusResult<FileInfo> {
-        // Let's create a new file ID.
-        // I guess the algo for generating new upload-id's can be
-        // configurable. But for now I don't really care, since UUIv4 works fine.
-        // Maybe update it later.
-        let file_id = Uuid::new_v4().simple().to_string();
+    async fn create_file(&self, file_info: &FileInfo) -> RustusResult<String> {
         // New path to file.
-        let file_path = self.data_file_path(file_id.as_str()).await?;
+        let file_path = self.data_file_path(file_info.id.as_str()).await?;
         // Creating new file.
         let mut file = OpenOptions::new()
             .write(true)
@@ -172,7 +114,7 @@ impl Storage for FileStorage {
             .await
             .map_err(|err| {
                 error!("{:?}", err);
-                RustusError::FileAlreadyExists(file_id.clone())
+                RustusError::FileAlreadyExists(file_info.id.clone())
             })?;
 
         // Let's write an empty string to the beginning of the file.
@@ -182,41 +124,20 @@ impl Storage for FileStorage {
             RustusError::UnableToWrite(file_path.display().to_string())
         })?;
         file.sync_all().await?;
-        // Creating new FileInfo object and saving it.
-        let file_info = FileInfo::new(
-            file_id.as_str(),
-            file_size,
-            Some(file_path.display().to_string()),
-            metadata,
-        );
-
-        self.info_storage.set_info(&file_info, true).await?;
 
-        Ok(file_info)
+        Ok(file_path.display().to_string())
     }
 
-    async fn remove_file(&self, file_id: &str) -> RustusResult<FileInfo> {
-        let info = self.info_storage.get_info(file_id).await?;
-        // Whoops, someone forgot to update the path field.
-        if info.path.is_none() {
-            return Err(RustusError::FileNotFound);
-        }
-        // Let's remove info first, so file won't show up
-        // In get_contents function.
-        self.info_storage.remove_info(file_id).await?;
-
+    async fn remove_file(&self, file_info: &FileInfo) -> RustusResult<()> {
         // Let's remove the file itself.
-        let data_path = PathBuf::from(info.path.as_ref().unwrap().clone());
+        let data_path = PathBuf::from(file_info.path.as_ref().unwrap().clone());
         if !data_path.exists() {
-            // Maybe we don't need error here,
-            // since if file doesn't exist,  we're done.
-            // FIXME: Find it out.
             return Err(RustusError::FileNotFound);
         }
         remove_file(data_path).await.map_err(|err| {
             error!("{:?}", err);
-            RustusError::UnableToRemove(String::from(file_id))
+            RustusError::UnableToRemove(file_info.id.clone())
         })?;
-        Ok(info)
+        Ok(())
     }
 }
diff --git a/src/storages/models/available_stores.rs b/src/storages/models/available_stores.rs
index 34880c18dd35383de0982d226c036f5d3431a572..c4f8d1b788a84fecb0bf29cd00bd89944a2c5761 100644
--- a/src/storages/models/available_stores.rs
+++ b/src/storages/models/available_stores.rs
@@ -1,4 +1,3 @@
-use crate::info_storages::InfoStorage;
 use crate::storages::file_storage;
 use crate::{from_str, RustusConf, Storage};
 use derive_more::{Display, From};
@@ -20,16 +19,10 @@ impl AvailableStores {
     /// `config` - Rustus configuration.
     /// `info_storage` - Storage for information about files.
     ///
-    pub fn get(
-        &self,
-        config: &RustusConf,
-        info_storage: Box<dyn InfoStorage + Sync + Send>,
-    ) -> Box<dyn Storage + Send + Sync> {
+    pub fn get(&self, config: &RustusConf) -> Box<dyn Storage + Send + Sync> {
         #[allow(clippy::single_match)]
         match self {
-            Self::FileStorage => {
-                Box::new(file_storage::FileStorage::new(config.clone(), info_storage))
-            }
+            Self::FileStorage => Box::new(file_storage::FileStorage::new(config.clone())),
         }
     }
 }
diff --git a/src/storages/models/storage.rs b/src/storages/models/storage.rs
index 31df02e7e22c7765d09baba5c07f93d6c9508495..e1294433f1dfff8fbbb8fdd30a7ba7a323a12e3b 100644
--- a/src/storages/models/storage.rs
+++ b/src/storages/models/storage.rs
@@ -2,10 +2,10 @@ use crate::errors::RustusResult;
 use crate::info_storages::FileInfo;
 use actix_files::NamedFile;
 use async_trait::async_trait;
-use std::collections::HashMap;
+use std::fmt::Display;
 
 #[async_trait]
-pub trait Storage {
+pub trait Storage: Display {
     /// Prepare storage before starting up server.
     ///
     /// Function to check if configuration is correct
@@ -17,24 +17,15 @@ pub trait Storage {
     /// be a problem later on.
     async fn prepare(&mut self) -> RustusResult<()>;
 
-    /// Get file information.
-    ///
-    /// This method returns all information about file.
-    ///
-    /// # Params
-    /// `file_id` - unique file identifier.
-    async fn get_file_info(&self, file_id: &str) -> RustusResult<FileInfo>;
-
     /// Get contents of a file.
     ///
     /// This method must return NamedFile since it
     /// is compatible with ActixWeb files interface.
-    ///
-    /// This method basically must call info storage method.
+    /// FIXME: change return type to stream.
     ///
     /// # Params
-    /// `file_id` - unique file identifier.
-    async fn get_contents(&self, file_id: &str) -> RustusResult<NamedFile>;
+    /// `file_info` - info about current file.
+    async fn get_contents(&self, file_info: &FileInfo) -> RustusResult<NamedFile>;
 
     /// Add bytes to the file.
     ///
@@ -44,24 +35,13 @@ pub trait Storage {
     /// # Errors
     ///
     /// Implementations MUST throw errors at following cases:
-    /// * Offset for request doesn't match offset we have in info storage.
-    /// * Updated length is provided, but we already know total size in bytes.
     /// * If the info about the file can't be found.
     /// * If the storage is offline.
     ///
     /// # Params
-    /// `file_id` - unique file identifier;
-    /// `request_offset` - offset from the client.
-    /// `updated_length` - total file size in bytes.
-    ///     This value is used by creation-defer-length extension.
+    /// `file_info` - info about current file.
     /// `bytes` - bytes to append to the file.
-    async fn add_bytes(
-        &self,
-        file_id: &str,
-        request_offset: usize,
-        updated_length: Option<usize>,
-        bytes: &[u8],
-    ) -> RustusResult<FileInfo>;
+    async fn add_bytes(&self, file_info: &FileInfo, bytes: &[u8]) -> RustusResult<()>;
 
     /// Create file in storage.
     ///
@@ -70,13 +50,8 @@ pub trait Storage {
     /// This function must use info storage to store information about the upload.
     ///
     /// # Params
-    /// `file_size` - Size of a file. It may be None if size is deferred;
-    /// `metadata` - Optional file meta-information;
-    async fn create_file(
-        &self,
-        file_size: Option<usize>,
-        metadata: Option<HashMap<String, String>>,
-    ) -> RustusResult<FileInfo>;
+    /// `file_info` - info about current file.
+    async fn create_file(&self, file_info: &FileInfo) -> RustusResult<String>;
 
     /// Remove file from storage
     ///
@@ -84,6 +59,6 @@ pub trait Storage {
     /// object if any.
     ///
     /// # Params
-    /// `file_id` - unique file identifier;
-    async fn remove_file(&self, file_id: &str) -> RustusResult<FileInfo>;
+    /// `file_info` - info about current file.
+    async fn remove_file(&self, file_info: &FileInfo) -> RustusResult<()>;
 }
diff --git a/src/utils/enums.rs b/src/utils/enums.rs
index 0ae1ae356c8ce37dff91115f368d390b861e88da..5109aeef353f609c345e4b70dde0a42ea0477ad3 100644
--- a/src/utils/enums.rs
+++ b/src/utils/enums.rs
@@ -1,3 +1,4 @@
+/// Implement `FromStr` for enums with `EnumIterator` trait from strum.
 #[macro_export]
 macro_rules! from_str {
     ($enum_name:ty, $name:literal) => {