diff --git a/dbrepo-data-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/TableEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/TableEndpoint.java
index 8ea36ff682ace6f66d1744662668b485f61cbc9a..78dc75f59d57a3eb8ee341a9ef914c88d0c57657 100644
--- a/dbrepo-data-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/TableEndpoint.java
+++ b/dbrepo-data-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/TableEndpoint.java
@@ -664,6 +664,7 @@ public class TableEndpoint extends RestEndpoint {
             throw new DatabaseUnavailableException("Failed to establish connection to database", e);
         }
         metadataServiceGateway.updateTableStatistics(databaseId, tableId, authorization);
+        storageService.saveImportEvent(databaseId, getId(principal), data.getLocation());
         return ResponseEntity.accepted()
                 .build();
     }
diff --git a/dbrepo-data-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UploadEndpoint.java b/dbrepo-data-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UploadEndpoint.java
index b7a88fc3f7c63116689dbbe26d4466ed43e0160b..97dea3f16e1784ef1ada9041c9827816f740f9c2 100644
--- a/dbrepo-data-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UploadEndpoint.java
+++ b/dbrepo-data-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/UploadEndpoint.java
@@ -1,9 +1,13 @@
 package at.ac.tuwien.ifs.dbrepo.endpoints;
 
+import at.ac.tuwien.ifs.dbrepo.core.api.database.ActionTypeDto;
+import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateStorageEventDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.file.UploadResponseDto;
 import at.ac.tuwien.ifs.dbrepo.core.exception.*;
+import at.ac.tuwien.ifs.dbrepo.gateway.MetadataServiceGateway;
+import at.ac.tuwien.ifs.dbrepo.mapper.DataMapper;
 import at.ac.tuwien.ifs.dbrepo.service.StorageService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.media.Content;
@@ -21,6 +25,7 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
+import java.security.Principal;
 
 @Log4j2
 @RestController
@@ -29,10 +34,12 @@ import java.io.IOException;
 public class UploadEndpoint extends RestEndpoint {
 
     private final StorageService storageService;
+    private final MetadataServiceGateway metadataServiceGateway;
 
     @Autowired
-    public UploadEndpoint(StorageService storageService) {
+    public UploadEndpoint(StorageService storageService, MetadataServiceGateway metadataServiceGateway) {
         this.storageService = storageService;
+        this.metadataServiceGateway = metadataServiceGateway;
     }
 
     @PostMapping
@@ -52,11 +59,13 @@ public class UploadEndpoint extends RestEndpoint {
                             mediaType = "application/json",
                             schema = @Schema(implementation = ApiErrorDto.class))}),
     })
-    public ResponseEntity<UploadResponseDto> create(@NotNull @RequestParam("file") MultipartFile file) throws DatabaseUnavailableException,
+    public ResponseEntity<UploadResponseDto> create(@NotNull @RequestParam("file") MultipartFile file,
+                                                    Principal principal) throws DatabaseUnavailableException,
             DatabaseNotFoundException, RemoteUnavailableException, ViewMalformedException, MetadataServiceException {
         log.debug("endpoint upload file, file.originalFilename={}", file.getOriginalFilename());
         try {
             final String key = storageService.putObject(file.getBytes());
+            storageService.saveUploadEvent(file, getId(principal), key);
             return ResponseEntity.status(HttpStatus.CREATED)
                     .body(UploadResponseDto.builder()
                             .s3Key(key)
diff --git a/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/StorageServiceIntegrationTest.java b/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/StorageServiceIntegrationTest.java
index 4f1c6efe40329961c213a463c1aa2fccb2168a33..8def1c1540da698c35b5480df04e59185b7b0719 100644
--- a/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/StorageServiceIntegrationTest.java
+++ b/dbrepo-data-service/rest-service/src/test/java/at/ac/tuwien/ifs/dbrepo/service/StorageServiceIntegrationTest.java
@@ -166,21 +166,6 @@ public class StorageServiceIntegrationTest extends BaseTest {
         });
     }
 
-    @Test
-    public void getResource_succeeds() throws StorageUnavailableException, StorageNotFoundException {
-
-        /* mock */
-        s3Client.putObject(PutObjectRequest.builder()
-                .key("s3key")
-                .bucket(s3Config.getS3Bucket())
-                .build(), RequestBody.fromFile(new File("src/test/resources/csv/weather_aus.csv")));
-
-        /* test */
-        final ExportResourceDto response = storageService.getResource(s3Config.getS3Bucket(), "s3key");
-        assertEquals("s3key", response.getFilename());
-        assertNotNull(response.getResource());
-    }
-
     @Test
     public void getResource_notFound_fails() {
 
diff --git a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/MetadataServiceGateway.java b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/MetadataServiceGateway.java
index c2f901c3cb25d5a923748e9109a2fc6075a45075..57e9498facfada7a2f11757c991931648535c94d 100644
--- a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/MetadataServiceGateway.java
+++ b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/MetadataServiceGateway.java
@@ -1,6 +1,7 @@
 package at.ac.tuwien.ifs.dbrepo.gateway;
 
 import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto;
+import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateStorageEventDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto;
@@ -15,6 +16,9 @@ import java.util.UUID;
 // todo ?
 public interface MetadataServiceGateway {
 
+    void saveStorageEvent(CreateStorageEventDto event) throws RemoteUnavailableException,
+            DatabaseNotFoundException, MetadataServiceException;
+
     /**
      * Get a container with given id from the metadata service.
      *
diff --git a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/MetadataServiceGatewayImpl.java b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/MetadataServiceGatewayImpl.java
index 7175151c109419f76d89f4f25c9a1a0912075d9e..8cdb57d07d70cca7d28a9adfdeeccdec92470134 100644
--- a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/MetadataServiceGatewayImpl.java
+++ b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/gateway/impl/MetadataServiceGatewayImpl.java
@@ -1,6 +1,7 @@
 package at.ac.tuwien.ifs.dbrepo.gateway.impl;
 
 import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto;
+import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateStorageEventDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto;
@@ -32,15 +33,37 @@ import java.util.UUID;
 public class MetadataServiceGatewayImpl implements MetadataServiceGateway {
 
     private final DataMapper dataMapper;
-    private final GatewayConfig gatewayConfig;
     private final RestTemplate internalRestTemplate;
+    private final GatewayConfig gatewayConfig;
 
     @Autowired
-    public MetadataServiceGatewayImpl(DataMapper dataMapper, GatewayConfig gatewayConfig,
-                                      @Qualifier("internalRestTemplate") RestTemplate internalRestTemplate) {
+    public MetadataServiceGatewayImpl(DataMapper dataMapper,
+                                      @Qualifier("internalRestTemplate") RestTemplate internalRestTemplate,
+                                      GatewayConfig gatewayConfig) {
         this.dataMapper = dataMapper;
-        this.gatewayConfig = gatewayConfig;
         this.internalRestTemplate = internalRestTemplate;
+        this.gatewayConfig = gatewayConfig;
+    }
+
+    @Override
+    public void saveStorageEvent(CreateStorageEventDto event) throws RemoteUnavailableException,
+            DatabaseNotFoundException, MetadataServiceException {
+        final ResponseEntity<Void> response;
+        final String url = "/api/database/" + event.getDatabaseId() + "/storage";
+        log.debug("save storage event in metadata service: {}", url);
+        try {
+            response = internalRestTemplate.exchange(url, HttpMethod.POST, new HttpEntity<>(event), Void.class);
+        } catch (ResourceAccessException | HttpServerErrorException e) {
+            log.error("Failed to save storage event: {}", e.getMessage());
+            throw new RemoteUnavailableException("Failed to save storage event: " + e.getMessage(), e);
+        } catch (HttpClientErrorException.NotFound e) {
+            log.error("Failed to find database/user: {}", e.getMessage());
+            throw new DatabaseNotFoundException("Failed to find database/user: " + e.getMessage(), e);
+        }
+        if (response.getStatusCode() != HttpStatus.ACCEPTED) {
+            log.error("Failed to save storage event: service responded unsuccessful: {}", response.getStatusCode());
+            throw new MetadataServiceException("Failed to save storage event: service responded unsuccessful: " + response.getStatusCode());
+        }
     }
 
     @Override
diff --git a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/mapper/DataMapper.java b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/mapper/DataMapper.java
index ddf7f9a882ab9b460f101b09a4a83b7c3b41e410..fdde65b4369df5ff20c666858bd9ba45bdae6a7b 100644
--- a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/mapper/DataMapper.java
+++ b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/mapper/DataMapper.java
@@ -1,10 +1,7 @@
 package at.ac.tuwien.ifs.dbrepo.mapper;
 
 import at.ac.tuwien.ifs.dbrepo.core.api.container.ContainerDto;
-import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseBriefDto;
-import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto;
-import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewColumnDto;
-import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto;
+import at.ac.tuwien.ifs.dbrepo.core.api.database.*;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.internal.CreateDatabaseDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.table.*;
diff --git a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/StorageService.java b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/StorageService.java
index 19540194abbb08be71fe741e5d0b9586ec992e47..3aa5cdff0ca4a82817383066632f283366e72e53 100644
--- a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/StorageService.java
+++ b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/StorageService.java
@@ -1,18 +1,23 @@
 package at.ac.tuwien.ifs.dbrepo.service;
 
 import at.ac.tuwien.ifs.dbrepo.core.api.ExportResourceDto;
-import at.ac.tuwien.ifs.dbrepo.core.exception.MalformedException;
-import at.ac.tuwien.ifs.dbrepo.core.exception.StorageNotFoundException;
-import at.ac.tuwien.ifs.dbrepo.core.exception.StorageUnavailableException;
-import at.ac.tuwien.ifs.dbrepo.core.exception.TableMalformedException;
+import at.ac.tuwien.ifs.dbrepo.core.exception.*;
 import org.apache.spark.sql.Dataset;
 import org.apache.spark.sql.Row;
+import org.springframework.web.multipart.MultipartFile;
 
 import java.io.InputStream;
 import java.util.List;
+import java.util.UUID;
 
 public interface StorageService {
 
+    void saveUploadEvent(MultipartFile file, UUID userId, String s3key) throws DatabaseNotFoundException,
+            RemoteUnavailableException, MetadataServiceException;
+
+    void saveImportEvent(UUID databaseId, UUID userId, String s3key) throws DatabaseNotFoundException,
+            RemoteUnavailableException, MetadataServiceException;
+
     String putObject(byte[] content);
 
     /**
@@ -49,28 +54,6 @@ public interface StorageService {
 
     void deleteObject(String bucket, String key);
 
-    /**
-     * Loads an object of the default export bucket from the Storage Service into an export resource.
-     *
-     * @param key The object key.
-     * @return The export resource, if successful.
-     * @throws StorageUnavailableException The object failed to be loaded from the Storage Service.
-     * @throws StorageNotFoundException    The key was not found in the Storage Service.
-     */
-    ExportResourceDto getResource(String key) throws StorageUnavailableException, StorageNotFoundException;
-
-    /**
-     * Loads an object of a bucket from the Storage Service into an export resource.
-     *
-     * @param bucket The bucket name.
-     * @param key    The object key.
-     * @return The export resource, if successful.
-     * @throws StorageUnavailableException The object failed to be loaded from the Storage Service.
-     * @throws StorageNotFoundException    The key was not found in the Storage Service.
-     */
-    ExportResourceDto getResource(String bucket, String key) throws StorageUnavailableException,
-            StorageNotFoundException;
-
     /**
      * Transforms the given dataset into a downloadable dataset.
      *
diff --git a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/StorageServiceS3Impl.java b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/StorageServiceS3Impl.java
index d29f5e2a2dc8c864402c4d0d66c4ab7de336461b..23cfa5b982409e927b811a1f2c88343aef363c10 100644
--- a/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/StorageServiceS3Impl.java
+++ b/dbrepo-data-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/StorageServiceS3Impl.java
@@ -1,12 +1,12 @@
 package at.ac.tuwien.ifs.dbrepo.service.impl;
 
 import at.ac.tuwien.ifs.dbrepo.config.S3Config;
-import at.ac.tuwien.ifs.dbrepo.service.StorageService;
 import at.ac.tuwien.ifs.dbrepo.core.api.ExportResourceDto;
-import at.ac.tuwien.ifs.dbrepo.core.exception.MalformedException;
-import at.ac.tuwien.ifs.dbrepo.core.exception.StorageNotFoundException;
-import at.ac.tuwien.ifs.dbrepo.core.exception.StorageUnavailableException;
-import at.ac.tuwien.ifs.dbrepo.core.exception.TableMalformedException;
+import at.ac.tuwien.ifs.dbrepo.core.api.database.ActionTypeDto;
+import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateStorageEventDto;
+import at.ac.tuwien.ifs.dbrepo.core.exception.*;
+import at.ac.tuwien.ifs.dbrepo.gateway.MetadataServiceGateway;
+import at.ac.tuwien.ifs.dbrepo.service.StorageService;
 import lombok.extern.log4j.Log4j2;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.apache.spark.sql.*;
@@ -15,16 +15,14 @@ import org.apache.spark.sql.types.StructField;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.core.io.InputStreamResource;
 import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
 import software.amazon.awssdk.core.sync.RequestBody;
 import software.amazon.awssdk.services.s3.S3Client;
 import software.amazon.awssdk.services.s3.model.*;
 
 import java.io.*;
 import java.nio.charset.Charset;
-import java.util.Arrays;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import static scala.collection.JavaConverters.asScalaIteratorConverter;
 
@@ -35,12 +33,39 @@ public class StorageServiceS3Impl implements StorageService {
     private final S3Config s3Config;
     private final S3Client s3Client;
     private final SparkSession sparkSession;
+    private final MetadataServiceGateway metadataServiceGateway;
 
     @Autowired
-    public StorageServiceS3Impl(S3Config s3Config, S3Client s3Client, SparkSession sparkSession) {
+    public StorageServiceS3Impl(S3Config s3Config, S3Client s3Client, SparkSession sparkSession,
+                                MetadataServiceGateway metadataServiceGateway) {
         this.s3Config = s3Config;
         this.s3Client = s3Client;
         this.sparkSession = sparkSession;
+        this.metadataServiceGateway = metadataServiceGateway;
+    }
+
+    @Override
+    public void saveUploadEvent(MultipartFile file, UUID userId, String s3key) throws DatabaseNotFoundException,
+            RemoteUnavailableException, MetadataServiceException {
+        final CreateStorageEventDto event = CreateStorageEventDto.builder()
+                .size(file.getSize())
+                .action(ActionTypeDto.UPLOAD)
+                .userId(userId)
+                .s3key(s3key)
+                .build();
+        metadataServiceGateway.saveStorageEvent(event);
+    }
+
+    @Override
+    public void saveImportEvent(UUID databaseId, UUID userId, String s3key) throws DatabaseNotFoundException,
+            RemoteUnavailableException, MetadataServiceException {
+        final CreateStorageEventDto event = CreateStorageEventDto.builder()
+                .databaseId(databaseId)
+                .action(ActionTypeDto.IMPORT)
+                .userId(userId)
+                .s3key(s3key)
+                .build();
+        metadataServiceGateway.saveStorageEvent(event);
     }
 
     @Override
@@ -98,22 +123,7 @@ public class StorageServiceS3Impl implements StorageService {
     }
 
     @Override
-    public ExportResourceDto getResource(String key) throws StorageNotFoundException, StorageUnavailableException {
-        return getResource(s3Config.getS3Bucket(), key);
-    }
-
-    @Override
-    public ExportResourceDto getResource(String bucket, String key) throws StorageNotFoundException,
-            StorageUnavailableException {
-        final InputStreamResource resource = new InputStreamResource(getObject(bucket, key));
-        log.trace("return export resource with filename: {}", key);
-        return ExportResourceDto.builder()
-                .resource(resource)
-                .filename(key)
-                .build();
-    }
-
-    @Override
+    // TODO should be export to S3 -> load from S3
     public ExportResourceDto transformDataset(Dataset<Row> dataset) throws StorageUnavailableException {
         final List<Map<String, String>> inMemory = dataset.collectAsList()
                 .stream()
diff --git a/dbrepo-metadata-db/1_setup-schema.sql b/dbrepo-metadata-db/1_setup-schema.sql
index 4ba9d70b174dca5b3481d8042f47c332afc4cf2b..8d07179e1bda9e161ea2cde6c835be74e281e73f 100644
--- a/dbrepo-metadata-db/1_setup-schema.sql
+++ b/dbrepo-metadata-db/1_setup-schema.sql
@@ -425,6 +425,7 @@ CREATE TABLE IF NOT EXISTS `mdb_identifier_creators`
 (
     id                                VARCHAR(36)  NOT NULL               DEFAULT UUID(),
     pid                               VARCHAR(36)  NOT NULL,
+    ordinal_position                  INT          NOT NULL,
     given_names                       TEXT,
     family_name                       TEXT,
     creator_name                      VARCHAR(255) NOT NULL,
@@ -502,6 +503,20 @@ CREATE TABLE IF NOT EXISTS `mdb_image_operators`
     UNIQUE (image_id, value)
 ) WITH SYSTEM VERSIONING;
 
+CREATE TABLE IF NOT EXISTS `mdb_databases_storages`
+(
+    id          VARCHAR(36)               NOT NULL DEFAULT UUID(),
+    database_id VARCHAR(36),
+    user_id     VARCHAR(36)               NOT NULL,
+    s3key       VARCHAR(100)              NOT NULL,
+    action      ENUM ('EXPORT', 'IMPORT') NOT NULL,
+    size        BIGINT COMMENT 'size in bytes',
+    created     TIMESTAMP                 NOT NULL DEFAULT NOW(),
+    PRIMARY KEY (`id`),
+    FOREIGN KEY (`database_id`) REFERENCES `mdb_databases` (`id`),
+    FOREIGN KEY (`user_id`) REFERENCES `mdb_users` (`id`)
+) WITH SYSTEM VERSIONING;
+
 COMMIT;
 
 BEGIN;
diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/StorageRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/StorageRepository.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a517d1b507a47c3822ab7cb5b75e2325853430f
--- /dev/null
+++ b/dbrepo-metadata-service/repositories/src/main/java/at/ac/tuwien/ifs/dbrepo/repository/StorageRepository.java
@@ -0,0 +1,12 @@
+package at.ac.tuwien.ifs.dbrepo.repository;
+
+import at.ac.tuwien.ifs.dbrepo.core.entity.database.StorageEvent;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+import java.util.UUID;
+
+@Repository
+public interface StorageRepository extends JpaRepository<StorageEvent, UUID> {
+
+}
diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/StorageEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/StorageEndpoint.java
new file mode 100644
index 0000000000000000000000000000000000000000..26df9678eb65df45521765120496393656bb8a9b
--- /dev/null
+++ b/dbrepo-metadata-service/rest-service/src/main/java/at/ac/tuwien/ifs/dbrepo/endpoints/StorageEndpoint.java
@@ -0,0 +1,75 @@
+package at.ac.tuwien.ifs.dbrepo.endpoints;
+
+import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateStorageEventDto;
+import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseAccessDto;
+import at.ac.tuwien.ifs.dbrepo.core.api.error.ApiErrorDto;
+import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database;
+import at.ac.tuwien.ifs.dbrepo.core.entity.user.User;
+import at.ac.tuwien.ifs.dbrepo.core.exception.DatabaseNotFoundException;
+import at.ac.tuwien.ifs.dbrepo.core.exception.UserNotFoundException;
+import at.ac.tuwien.ifs.dbrepo.service.DatabaseService;
+import at.ac.tuwien.ifs.dbrepo.service.UserService;
+import io.micrometer.observation.annotation.Observed;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.media.Content;
+import io.swagger.v3.oas.annotations.media.Schema;
+import io.swagger.v3.oas.annotations.responses.ApiResponse;
+import io.swagger.v3.oas.annotations.responses.ApiResponses;
+import io.swagger.v3.oas.annotations.security.SecurityRequirement;
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotNull;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.UUID;
+
+@Log4j2
+@RestController
+@CrossOrigin(origins = "*")
+@RequestMapping(path = "/api/database/{databaseId}/storage")
+public class StorageEndpoint extends AbstractEndpoint {
+
+    private final UserService userService;
+    private final DatabaseService databaseService;
+
+    @Autowired
+    public StorageEndpoint(UserService userService, DatabaseService databaseService) {
+        this.userService = userService;
+        this.databaseService = databaseService;
+    }
+
+    @PostMapping
+    @Transactional
+    @Observed(name = "dbrepo_storage_event")
+    @PreAuthorize("hasAuthority('system')")
+    @Operation(summary = "Log storage event",
+            description = "Logs a storage event in the Metadata Database. Requires role `system`.",
+            security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")})
+    @ApiResponses(value = {
+            @ApiResponse(responseCode = "201",
+                    description = "Saved successfully",
+                    content = {@Content(
+                            mediaType = "application/json",
+                            schema = @Schema(implementation = DatabaseAccessDto.class))}),
+            @ApiResponse(responseCode = "404",
+                    description = "Database or user not found",
+                    content = {@Content(
+                            mediaType = "application/json",
+                            schema = @Schema(implementation = ApiErrorDto.class))}),
+    })
+    public ResponseEntity<DatabaseAccessDto> save(@NotNull @PathVariable("databaseId") UUID databaseId,
+                                                  @Valid @RequestBody CreateStorageEventDto data)
+            throws DatabaseNotFoundException, UserNotFoundException {
+        log.debug("endpoint save storage event, databaseId={}, data.action={}", databaseId, data.getAction());
+        final Database database = databaseService.findById(databaseId);
+        final User user = userService.findById(data.getUserId());
+        databaseService.saveStorageEvent(database, user, data);
+        return ResponseEntity.accepted()
+                .build();
+    }
+
+}
diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseService.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseService.java
index 351e383b05ed01cbffbf4e3685f79b2b279b2eb2..107c517542e26b5e415a9052370e401888038e3e 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseService.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/DatabaseService.java
@@ -1,9 +1,11 @@
 package at.ac.tuwien.ifs.dbrepo.service;
 
 import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateDatabaseDto;
+import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateStorageEventDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseModifyVisibilityDto;
 import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container;
 import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database;
+import at.ac.tuwien.ifs.dbrepo.core.entity.database.StorageEvent;
 import at.ac.tuwien.ifs.dbrepo.core.entity.user.User;
 import at.ac.tuwien.ifs.dbrepo.core.exception.*;
 import org.springframework.stereotype.Service;
@@ -63,6 +65,8 @@ public interface DatabaseService {
      */
     List<Database> findAllPublicOrSchemaPublicByInternalName(String internalName);
 
+    StorageEvent saveStorageEvent(Database database, User user, CreateStorageEventDto data);
+
     /**
      * Find a database by given id.
      *
diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DatabaseServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DatabaseServiceImpl.java
index 6cfa0180a8891c97e49fdcebd1c2923da8088adf..932f581d61f16b0098f34cc421aeef9aaf1c37e1 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DatabaseServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/DatabaseServiceImpl.java
@@ -1,13 +1,11 @@
 package at.ac.tuwien.ifs.dbrepo.service.impl;
 
-import at.ac.tuwien.ifs.dbrepo.core.api.database.CreateDatabaseDto;
-import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseDto;
-import at.ac.tuwien.ifs.dbrepo.core.api.database.DatabaseModifyVisibilityDto;
-import at.ac.tuwien.ifs.dbrepo.core.api.database.ViewDto;
+import at.ac.tuwien.ifs.dbrepo.core.api.database.*;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.table.TableDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.user.internal.UpdateUserPasswordDto;
 import at.ac.tuwien.ifs.dbrepo.core.entity.container.Container;
 import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database;
+import at.ac.tuwien.ifs.dbrepo.core.entity.database.StorageEvent;
 import at.ac.tuwien.ifs.dbrepo.core.entity.database.View;
 import at.ac.tuwien.ifs.dbrepo.core.entity.database.ViewColumn;
 import at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table;
@@ -22,6 +20,7 @@ import at.ac.tuwien.ifs.dbrepo.core.mapper.MetadataMapper;
 import at.ac.tuwien.ifs.dbrepo.gateway.DataServiceGateway;
 import at.ac.tuwien.ifs.dbrepo.gateway.SearchServiceGateway;
 import at.ac.tuwien.ifs.dbrepo.repository.DatabaseRepository;
+import at.ac.tuwien.ifs.dbrepo.repository.StorageRepository;
 import at.ac.tuwien.ifs.dbrepo.service.DatabaseService;
 import lombok.extern.log4j.Log4j2;
 import org.apache.commons.lang3.RandomStringUtils;
@@ -39,14 +38,17 @@ import java.util.UUID;
 public class DatabaseServiceImpl implements DatabaseService {
 
     private final MetadataMapper metadataMapper;
+    private final StorageRepository storageRepository;
     private final DatabaseRepository databaseRepository;
     private final DataServiceGateway dataServiceGateway;
     private final SearchServiceGateway searchServiceGateway;
 
     @Autowired
-    public DatabaseServiceImpl(MetadataMapper metadataMapper, DatabaseRepository databaseRepository,
-                               DataServiceGateway dataServiceGateway, SearchServiceGateway searchServiceGateway) {
+    public DatabaseServiceImpl(MetadataMapper metadataMapper, StorageRepository storageRepository,
+                               DatabaseRepository databaseRepository, DataServiceGateway dataServiceGateway,
+                               SearchServiceGateway searchServiceGateway) {
         this.metadataMapper = metadataMapper;
+        this.storageRepository = storageRepository;
         this.databaseRepository = databaseRepository;
         this.dataServiceGateway = dataServiceGateway;
         this.searchServiceGateway = searchServiceGateway;
@@ -82,6 +84,16 @@ public class DatabaseServiceImpl implements DatabaseService {
         return databaseRepository.findAllPublicOrSchemaPublicByInternalNameDesc(internalName);
     }
 
+    @Override
+    public StorageEvent saveStorageEvent(Database database, User user, CreateStorageEventDto data) {
+        final StorageEvent entity = metadataMapper.createStorageEventDtoToStorageEvent(data);
+        entity.setUser(user);
+        entity.setDatabase(database);
+        final StorageEvent event = storageRepository.save(entity);
+        log.info("Saved storage event {} for database with id: {}", event.getAction(), event.getDatabase().getId());
+        return event;
+    }
+
     @Override
     @Transactional(readOnly = true)
     public Database findById(UUID id) throws DatabaseNotFoundException {
diff --git a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/IdentifierServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/IdentifierServiceImpl.java
index f8b2c273e8c9032a103b327f84892528aad7826f..4257c7b5018e15940deaa254ef54e8575c422af9 100644
--- a/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/IdentifierServiceImpl.java
+++ b/dbrepo-metadata-service/services/src/main/java/at/ac/tuwien/ifs/dbrepo/service/impl/IdentifierServiceImpl.java
@@ -1,11 +1,11 @@
 package at.ac.tuwien.ifs.dbrepo.service.impl;
 
+import at.ac.tuwien.ifs.dbrepo.config.MetadataConfig;
 import at.ac.tuwien.ifs.dbrepo.core.api.database.query.QueryDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.identifier.BibliographyTypeDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.identifier.CreateIdentifierDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierSaveDto;
 import at.ac.tuwien.ifs.dbrepo.core.api.identifier.IdentifierTypeDto;
-import at.ac.tuwien.ifs.dbrepo.config.MetadataConfig;
 import at.ac.tuwien.ifs.dbrepo.core.entity.database.Database;
 import at.ac.tuwien.ifs.dbrepo.core.entity.database.LanguageType;
 import at.ac.tuwien.ifs.dbrepo.core.entity.database.View;
@@ -184,40 +184,60 @@ public class IdentifierServiceImpl implements IdentifierService {
                     .stream()
                     .map(metadataMapper::creatorCreateDtoToCreator)
                     .toList()));
+            final int[] idx = new int[]{0};
             identifier.getCreators()
-                    .forEach(c -> c.setIdentifier(identifier));
+                    .forEach(c -> {
+                        c.setOrdinalPosition(idx[0]++);
+                        c.setIdentifier(identifier);
+                    });
         }
         if (data.getRelatedIdentifiers() != null) {
             identifier.setRelatedIdentifiers(new LinkedList<>(data.getRelatedIdentifiers()
                     .stream()
                     .map(metadataMapper::relatedIdentifierCreateDtoToRelatedIdentifier)
                     .toList()));
+            final int[] idx = new int[]{0};
             identifier.getRelatedIdentifiers()
-                    .forEach(r -> r.setIdentifier(identifier));
+                    .forEach(r -> {
+                        r.setOrdinalPosition(idx[0]++);
+                        r.setIdentifier(identifier);
+                    });
         }
         if (data.getTitles() != null) {
             identifier.setTitles(new LinkedList<>(data.getTitles()
                     .stream()
                     .map(metadataMapper::identifierCreateTitleDtoToIdentifierTitle)
                     .toList()));
+            final int[] idx = new int[]{0};
             identifier.getTitles()
-                    .forEach(t -> t.setIdentifier(identifier));
+                    .forEach(t -> {
+                        t.setOrdinalPosition(idx[0]++);
+                        t.setIdentifier(identifier);
+                    });
         }
         if (data.getDescriptions() != null) {
             identifier.setDescriptions(new LinkedList<>(data.getDescriptions()
                     .stream()
                     .map(metadataMapper::identifierCreateDescriptionDtoToIdentifierDescription)
                     .toList()));
+            final int[] idx = new int[]{0};
             identifier.getDescriptions()
-                    .forEach(d -> d.setIdentifier(identifier));
+                    .forEach(d -> {
+                        d.setOrdinalPosition(idx[0]++);
+                        d.setIdentifier(identifier);
+                    });
         }
         if (data.getFunders() != null) {
             identifier.setFunders(new LinkedList<>(data.getFunders()
                     .stream()
                     .map(metadataMapper::identifierFunderSaveDtoToIdentifierFunder)
                     .toList()));
+            final int[] idx = new int[]{0};
             identifier.getFunders()
-                    .forEach(f -> f.setIdentifier(identifier));
+                    .forEach(f -> {
+                        f.setOrdinalPosition(idx[0]++);
+                        f.setIdentifier(identifier);
+                    });
         }
         return save(identifier);
     }
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ActionTypeDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ActionTypeDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..b87d28c2fb3b691a0c3cf987aa6f438de813a1a5
--- /dev/null
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/ActionTypeDto.java
@@ -0,0 +1,28 @@
+package at.ac.tuwien.ifs.dbrepo.core.api.database;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.Getter;
+
+@Getter
+public enum ActionTypeDto {
+
+    @JsonProperty("export")
+    EXPORT("export"),
+
+    @JsonProperty("import")
+    IMPORT("import"),
+
+    @JsonProperty("upload")
+    UPLOAD("upload");
+
+    private final String value;
+
+    ActionTypeDto(String value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return this.value;
+    }
+}
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateStorageEventDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateStorageEventDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..0987240fc615bf136b0987d8aa531fa66d27edb5
--- /dev/null
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/CreateStorageEventDto.java
@@ -0,0 +1,36 @@
+package at.ac.tuwien.ifs.dbrepo.core.api.database;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.*;
+import lombok.extern.jackson.Jacksonized;
+
+import java.util.UUID;
+
+@Getter
+@Setter
+@Builder
+@EqualsAndHashCode
+@NoArgsConstructor
+@AllArgsConstructor
+@Jacksonized
+@ToString
+public class CreateStorageEventDto {
+
+    @NotNull
+    @JsonProperty("user_id")
+    private UUID userId;
+
+    @JsonProperty("database_id")
+    private UUID databaseId;
+
+    @NotBlank
+    private String s3key;
+
+    private Long size;
+
+    @NotNull
+    private ActionTypeDto action;
+
+}
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/StorageEventDto.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/StorageEventDto.java
new file mode 100644
index 0000000000000000000000000000000000000000..9678426318bc5525e4824eabfd7c439fa0dfba15
--- /dev/null
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/api/database/StorageEventDto.java
@@ -0,0 +1,39 @@
+package at.ac.tuwien.ifs.dbrepo.core.api.database;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.*;
+import lombok.extern.jackson.Jacksonized;
+
+import java.util.UUID;
+
+@Getter
+@Setter
+@Builder
+@EqualsAndHashCode
+@NoArgsConstructor
+@AllArgsConstructor
+@Jacksonized
+@ToString
+public class StorageEventDto {
+
+    @NotNull
+    private UUID id;
+
+    @NotNull
+    @JsonProperty("user_id")
+    private UUID userId;
+
+    @NotNull
+    private UUID databaseId;
+
+    @NotBlank
+    private String s3key;
+
+    private Long size;
+
+    @NotNull
+    private ActionTypeDto action;
+
+}
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/ActionType.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/ActionType.java
new file mode 100644
index 0000000000000000000000000000000000000000..ae50d2673af93483bc3cc4937d000dba7115620f
--- /dev/null
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/ActionType.java
@@ -0,0 +1,10 @@
+package at.ac.tuwien.ifs.dbrepo.core.entity.database;
+
+import lombok.Getter;
+
+@Getter
+public enum ActionType {
+    EXPORT,
+    IMPORT,
+    UPLOAD;
+}
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/Database.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/Database.java
index 2aefc232a30908654572a89b8a894abbc00d8c96..bb9e35cf54834eaee378fecd41a29697148fda69 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/Database.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/Database.java
@@ -91,19 +91,23 @@ public class Database implements Serializable {
 
     @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}, mappedBy = "database")
     @Where(clause = "identifier_type='DATABASE'")
-    @OrderBy("id DESC")
+    @OrderBy("created DESC")
     private List<Identifier> identifiers;
 
     @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}, mappedBy = "database")
     @Where(clause = "identifier_type='SUBSET'")
-    @OrderBy("id DESC")
+    @OrderBy("created DESC")
     private List<Identifier> subsets;
 
-    @OrderBy("id DESC")
+    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.MERGE}, mappedBy = "database")
+    @OrderBy("created DESC")
+    private List<StorageEvent> storageEvents;
+
+    @OrderBy("created DESC")
     @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "database", orphanRemoval = true)
     private List<at.ac.tuwien.ifs.dbrepo.core.entity.database.table.Table> tables;
 
-    @OrderBy("id DESC")
+    @OrderBy("created DESC")
     @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "database", orphanRemoval = true)
     private List<View> views;
 
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/StorageEvent.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/StorageEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..a7ec0f35a47256f5dd7498814725f130a57298ac
--- /dev/null
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/StorageEvent.java
@@ -0,0 +1,73 @@
+package at.ac.tuwien.ifs.dbrepo.core.entity.database;
+
+import at.ac.tuwien.ifs.dbrepo.core.entity.user.User;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import jakarta.persistence.*;
+import lombok.*;
+import org.hibernate.annotations.JdbcTypeCode;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+import java.time.Instant;
+import java.util.UUID;
+
+@Data
+@Entity
+@Builder
+@ToString
+@AllArgsConstructor
+@NoArgsConstructor
+@EqualsAndHashCode
+@EntityListeners(AuditingEntityListener.class)
+@Table(name = "mdb_databases_storages")
+public class StorageEvent {
+
+    @Id
+    @JdbcTypeCode(java.sql.Types.VARCHAR)
+    @Column(columnDefinition = "VARCHAR(36)")
+    private UUID id;
+
+    @ToString.Exclude
+    @JdbcTypeCode(java.sql.Types.VARCHAR)
+    @Column(name = "user_id", nullable = false, columnDefinition = "VARCHAR(36)")
+    private UUID userId;
+
+    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
+    @JoinColumns({
+            @JoinColumn(name = "user_id", referencedColumnName = "id", insertable = false, updatable = false)
+    })
+    private User user;
+
+    @ToString.Exclude
+    @JdbcTypeCode(java.sql.Types.VARCHAR)
+    @Column(name = "database_id", columnDefinition = "VARCHAR(36)")
+    private UUID databaseId;
+
+    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
+    @JoinColumns({
+            @JoinColumn(name = "database_id", referencedColumnName = "id", insertable = false, updatable = false)
+    })
+    private Database database;
+
+    @Column(nullable = false, columnDefinition = "VARCHAR(100)")
+    private String s3key;
+
+    private Long size;
+
+    @Column(nullable = false, columnDefinition = "ENUM('EXPORT', 'IMPORT')")
+    private ActionType action;
+
+    @EqualsAndHashCode.Exclude
+    @CreatedDate
+    @Column(nullable = false, updatable = false, columnDefinition = "TIMESTAMP default NOW()")
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX", timezone = "UTC")
+    private Instant created;
+
+    @PrePersist
+    public void prePersist() {
+        if (this.id == null) {
+            this.id = UUID.randomUUID();
+        }
+    }
+
+}
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/View.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/View.java
index d84b75530b1b5dd2b27a896461f6d86671588ea1..38680c01db39d2e66e5cc8866e4689a0f5b13e0b 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/View.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/View.java
@@ -81,7 +81,7 @@ public class View {
             @JoinColumn(name = "dbid", referencedColumnName = "vdbid", insertable = false, updatable = false)
     })
     @Where(clause = "identifier_type='VIEW'")
-    @OrderBy("id DESC")
+    @OrderBy("created DESC")
     private List<Identifier> identifiers;
 
     @ToString.Exclude
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/Table.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/Table.java
index 42faf301ca49b73bfc4bcded087b9c005a5c764a..41a5c950a34bf5dbad6e30b762798256e5837600 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/Table.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/database/table/Table.java
@@ -83,7 +83,7 @@ public class Table {
             @JoinColumn(name = "dbid", referencedColumnName = "tdbid", insertable = false, updatable = false)
     })
     @Where(clause = "identifier_type='TABLE'")
-    @OrderBy("id DESC")
+    @OrderBy("created DESC")
     private List<Identifier> identifiers;
 
     @Embedded
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Creator.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Creator.java
index 8a2bcf25e2e0a7bfc4add70406bc84503cb959d2..428d70d719cb3ca2751d29935787608cc7ab0678 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Creator.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Creator.java
@@ -23,6 +23,9 @@ public class Creator {
     @Column(columnDefinition = "VARCHAR(36)")
     private UUID id;
 
+    @Column
+    private Integer ordinalPosition;
+
     @Column(name = "given_names")
     private String firstname;
 
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Identifier.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Identifier.java
index 04471509c6cd711b745f1a9060227d869f2dcb33..15fd36ca8eac8723c753d3315ccbe9ff8959dcea 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Identifier.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/Identifier.java
@@ -54,7 +54,7 @@ public class Identifier implements Serializable {
      * Creators are created/updated/deleted by the Identifier entity.
      */
     @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "identifier")
-    @OrderBy("id")
+    @OrderBy("ordinalPosition ASC")
     private List<Creator> creators;
 
     @Column(nullable = false)
@@ -72,21 +72,21 @@ public class Identifier implements Serializable {
      * Titles are created/updated/deleted by the Identifier entity.
      */
     @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "identifier")
-    @OrderBy("id")
+    @OrderBy("ordinalPosition ASC")
     private List<IdentifierTitle> titles;
 
     /**
      * Descriptions are created/updated/deleted by the Identifier entity.
      */
     @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "identifier")
-    @OrderBy("id")
+    @OrderBy("ordinalPosition ASC")
     private List<IdentifierDescription> descriptions;
 
     /**
      * Funders are created/updated/deleted by the Identifier entity.
      */
     @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "identifier")
-    @OrderBy("id")
+    @OrderBy("ordinalPosition ASC")
     private List<IdentifierFunder> funders;
 
     /**
@@ -144,7 +144,7 @@ public class Identifier implements Serializable {
     private Database database;
 
     @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.ALL, CascadeType.PERSIST}, mappedBy = "identifier")
-    @OrderBy("id")
+    @OrderBy("ordinalPosition ASC")
     private List<RelatedIdentifier> relatedIdentifiers;
 
     @Column
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierDescription.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierDescription.java
index ab73de406ee607253f14a182a4c9af9f748666dc..72c531c82b4e7d081a1112513a633040c3cc4e6c 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierDescription.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierDescription.java
@@ -25,6 +25,9 @@ public class IdentifierDescription implements Serializable {
     @Column(columnDefinition = "VARCHAR(36)")
     private UUID id;
 
+    @Column
+    private Integer ordinalPosition;
+
     @Column(nullable = false, columnDefinition = "TEXT")
     private String description;
 
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunder.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunder.java
index eb3c21e61794726e53cabfcfe8e32e58072789d9..252957f8e43e6915a7b6361a3d9d92e8c707a234 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunder.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierFunder.java
@@ -24,6 +24,9 @@ public class IdentifierFunder implements Serializable {
     @Column(columnDefinition = "VARCHAR(36)")
     private UUID id;
 
+    @Column
+    private Integer ordinalPosition;
+
     @Column(nullable = false)
     private String funderName;
 
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierTitle.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierTitle.java
index 8dbbdac0a9dd7804f61315892201c5df53857403..c19a02e9873ccf0654d81d6ca384c3d0ee748dd1 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierTitle.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/IdentifierTitle.java
@@ -25,6 +25,9 @@ public class IdentifierTitle implements Serializable {
     @Column(columnDefinition = "VARCHAR(36)")
     private UUID id;
 
+    @Column
+    private Integer ordinalPosition;
+
     @Column(nullable = false, columnDefinition = "TEXT")
     private String title;
 
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedIdentifier.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedIdentifier.java
index e0eb28d11b7c68753c2f99564d28bb59be7fbf17..29fcf641599b08ca15d14fc7a360eb8e1a934973 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedIdentifier.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/entity/identifier/RelatedIdentifier.java
@@ -25,6 +25,9 @@ public class RelatedIdentifier {
     @Column(columnDefinition = "VARCHAR(36)")
     private UUID id;
 
+    @Column
+    private Integer ordinalPosition;
+
     @Column(nullable = false)
     private String value;
 
diff --git a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/mapper/MetadataMapper.java b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/mapper/MetadataMapper.java
index 0ed6e783c033c7f85e9f3278552374de8ab6f50e..80aa58ef5239a47d7dbbbdbf4e1e1c4f519efd76 100644
--- a/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/mapper/MetadataMapper.java
+++ b/lib/java/dbrepo-core/src/main/java/at/ac/tuwien/ifs/dbrepo/core/mapper/MetadataMapper.java
@@ -104,6 +104,12 @@ public interface MetadataMapper {
     })
     DataTypeDto dataTypeToDataTypeDto(DataType data);
 
+    StorageEventDto storageEventToStorageEventDto(StorageEvent data);
+
+    StorageEvent storageEventDtoToStorageEvent(StorageEventDto data);
+
+    StorageEvent createStorageEventDtoToStorageEvent(CreateStorageEventDto data);
+
     @Mappings({
             @Mapping(target = "databaseName", source = "internalName"),
             @Mapping(target = "ownerUsername", source = "owner.username")