diff --git a/bob/bio/vein/config/database/protocol_utfvp/full.py b/bob/bio/vein/config/database/protocol_utfvp/full.py
deleted file mode 100644
index 5a94135aa2a32dde74a63a7e2b6548a957d0701e..0000000000000000000000000000000000000000
--- a/bob/bio/vein/config/database/protocol_utfvp/full.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# author: Yannick Dayer <yannick.dayer@idiap.ch>
-# Wed 21 Oct 2020 10:32:56 UTC+02
-
-# This is a config file for bob.bio.vein
-# It defines the database protocol to use with the Database Interface for the
-# utfvp dataset, defined at bob.db.utfvp.
-
-# It is defined as a resource in the setup file of this package.
-
-# Usage:
-# $ bob bio pipelines vanilla-biometrics <pipeline> full utfvp
-# or:
-# $ bob bio pipelines vanilla-biometrics -p <pipeline> full utfvp
-
-# The protocol resource must be specified before the database resource.
-
-
-# Available protocols are (some require the creation of your own config file):
-# '1vsall', 'full', 'fullLeftIndex', 'fullLeftMiddle', 'fullLeftRing',
-# 'fullRightIndex', 'fullRightMiddle', 'fullRightRing', 'nom', 'nomLeftIndex',
-# 'nomLeftMiddle', 'nomLeftRing', 'nomRightIndex', 'nomRightMiddle',
-# 'nomRightRing'
-
-
-protocol = 'full'
-
diff --git a/bob/bio/vein/config/database/protocol_utfvp/nom.py b/bob/bio/vein/config/database/protocol_utfvp/nom.py
deleted file mode 100644
index 415379379f8c78f84dedbfec1396865f713db0c6..0000000000000000000000000000000000000000
--- a/bob/bio/vein/config/database/protocol_utfvp/nom.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# author: Yannick Dayer <yannick.dayer@idiap.ch>
-# Wed 21 Oct 2020 10:30:22 UTC+02
-
-# This is a config file for bob.bio.vein
-# It defines the database protocol to use with the Database Interface for the
-# utfvp dataset, defined at bob.db.utfvp.
-
-# It is defined as a resource in the setup file of this package.
-
-# Usage:
-# $ bob bio pipelines vanilla-biometrics <pipeline> nom utfvp
-# or:
-# $ bob bio pipelines vanilla-biometrics -p <pipeline> nom utfvp
-
-# The protocol resource must be specified before the database resource.
-
-
-# Available protocols are (some require the creation of your own config file):
-# '1vsall', 'full', 'fullLeftIndex', 'fullLeftMiddle', 'fullLeftRing',
-# 'fullRightIndex', 'fullRightMiddle', 'fullRightRing', 'nom', 'nomLeftIndex',
-# 'nomLeftMiddle', 'nomLeftRing', 'nomRightIndex', 'nomRightMiddle',
-# 'nomRightRing'
-
-
-# This will be the default protocol if none is specified.
-
-protocol = 'nom'
-
diff --git a/bob/bio/vein/config/database/protocol_utfvp/one_vs_all.py b/bob/bio/vein/config/database/protocol_utfvp/one_vs_all.py
deleted file mode 100644
index d5cc70894a888fb1425bbc502bd607de0df11e0f..0000000000000000000000000000000000000000
--- a/bob/bio/vein/config/database/protocol_utfvp/one_vs_all.py
+++ /dev/null
@@ -1,26 +0,0 @@
-# author: Yannick Dayer <yannick.dayer@idiap.ch>
-# Wed 21 Oct 2020 10:34:41 UTC+02
-
-# This is a config file for bob.bio.vein
-# It defines the database protocol to use with the Database Interface for the
-# utfvp dataset, defined at bob.db.utfvp.
-
-# It is defined as a resource in the setup file of this package.
-
-# Usage:
-# $ bob bio pipelines vanilla-biometrics <pipeline> 1vsall utfvp
-# or:
-# $ bob bio pipelines vanilla-biometrics -p <pipeline> 1vsall utfvp
-
-# The protocol resource must be specified before the database resource.
-
-
-# Available protocols are (some require the creation of your own config file):
-# '1vsall', 'full', 'fullLeftIndex', 'fullLeftMiddle', 'fullLeftRing',
-# 'fullRightIndex', 'fullRightMiddle', 'fullRightRing', 'nom', 'nomLeftIndex',
-# 'nomLeftMiddle', 'nomLeftRing', 'nomRightIndex', 'nomRightMiddle',
-# 'nomRightRing'
-
-
-protocol = 'full'
-
diff --git a/bob/bio/vein/config/database/utfvp.py b/bob/bio/vein/config/database/utfvp.py
deleted file mode 100644
index fe3a7c8fc1e93d71417ad30392e56cde60add223..0000000000000000000000000000000000000000
--- a/bob/bio/vein/config/database/utfvp.py
+++ /dev/null
@@ -1,61 +0,0 @@
-#!/usr/bin/env python
-# vim: set fileencoding=utf-8 :
-# Tue 27 Sep 2016 16:47:45 CEST
-
-"""`UTFVP`_ is a database for biometric fingervein recognition
-
-The University of Twente Finger Vascular Pattern (UTFVP) Database is made
-publically available in order to support and stimulate research efforts in the
-area of developing, testing and evaluating algorithms for vascular patter
-recognition. The University of Twente, Enschede, The Netherlands (henceforth,
-UT) owns copyright of and serves as the source for the UTFVP database, which is
-now distributed to any research group approved by the UTFVP principal
-investigator. The reference citation is [TV13]_.
-
-You can download the raw data of the `UTFVP`_ database by following the link.
-
-.. include:: links.rst
-"""
-
-from bob.extension import rc
-from bob.bio.vein.database.utfvp import Database
-from bob.bio.base.pipelines.vanilla_biometrics import DatabaseConnector
-
-import logging
-
-logger = logging.getLogger("bob.bio.vein")
-
-_utfvp_directory = rc.get("bob.db.utfvp.directory", "")
-"""Value in ``~/.bobrc`` for this dataset directory"""
-
-# Set default protocol if not given via a config file
-if "protocol" not in locals():
-    logger.info("protocol not specified, using default: 'nom'")
-    protocol = "nom"
-
-legacy_database = Database(
-    original_directory=_utfvp_directory, original_extension=".png", protocol=protocol,
-)
-"""The :py:class:`bob.bio.base.database.BioDatabase` derivative with UTFVP settings
-"""
-
-database = DatabaseConnector(
-    legacy_database, annotation_type=None, fixed_positions=None
-)
-"""
-The database interface wrapped for vanilla-biometrics
-
-.. warning::
-
-   This class only provides a programmatic interface to load data in an orderly
-   manner, respecting usage protocols. It does **not** contain the raw
-   datafiles. You should procure those yourself.
-
-Notice that ``original_directory`` is set to ``rc[bob.db.utfvp.directory]``.
-You must make sure to set this value with
-``bob config set bob.db.utfvp.directory`` to the place where you actually
-installed the `utfvp`_ dataset, as explained in the section
-:ref:`bob.bio.vein.baselines`.
-"""
-
-logger.debug(f"Loaded database utfvp config file, using protocol '{protocol}'.")
diff --git a/bob/bio/vein/config/database/utfvp_1vsall.py b/bob/bio/vein/config/database/utfvp_1vsall.py
new file mode 100644
index 0000000000000000000000000000000000000000..bfc8b7fa08f2259aa93f39643891854146637ee9
--- /dev/null
+++ b/bob/bio/vein/config/database/utfvp_1vsall.py
@@ -0,0 +1,3 @@
+from bob.bio.vein.database.utfvp import UtfvpDatabase
+
+database = UtfvpDatabase(protocol="1vsall")
diff --git a/bob/bio/vein/config/database/utfvp_full.py b/bob/bio/vein/config/database/utfvp_full.py
new file mode 100644
index 0000000000000000000000000000000000000000..a8e01a7d77f23e71daa2980bc8ddf8e7f92402f3
--- /dev/null
+++ b/bob/bio/vein/config/database/utfvp_full.py
@@ -0,0 +1,3 @@
+from bob.bio.vein.database.utfvp import UtfvpDatabase
+
+database = UtfvpDatabase(protocol="full")
diff --git a/bob/bio/vein/config/database/utfvp_nom.py b/bob/bio/vein/config/database/utfvp_nom.py
new file mode 100644
index 0000000000000000000000000000000000000000..90a62ac4bd74f1ad075b66024bb0ebf02310afbc
--- /dev/null
+++ b/bob/bio/vein/config/database/utfvp_nom.py
@@ -0,0 +1,3 @@
+from bob.bio.vein.database.utfvp import UtfvpDatabase
+
+database = UtfvpDatabase(protocol="nom")
diff --git a/bob/bio/vein/database/utfvp.py b/bob/bio/vein/database/utfvp.py
index 8ed153abbce616ba8e41ab21fd0e7c20aa94046e..2b7552cb3883d9fb545617df766db9e78a9f1c95 100644
--- a/bob/bio/vein/database/utfvp.py
+++ b/bob/bio/vein/database/utfvp.py
@@ -1,83 +1,56 @@
 #!/usr/bin/env python
 # vim: set fileencoding=utf-8 :
-# Tue 27 Sep 2016 16:48:57 CEST
+# Victor <vbros@idiap.ch>
 
+"""
+  Utfvp database implementation
+"""
 
-from bob.bio.base.database import BioFile, BioDatabase
+from bob.bio.base.database import CSVDataset
+from bob.bio.base.database import CSVToSampleLoaderBiometrics
+from bob.extension import rc
+from bob.extension.download import get_file
+import bob.io.image
 
-from . import AnnotatedArray
-from ..preprocessor.utils import poly_to_mask
 
-
-class File(BioFile):
+class UtfvpDatabase(CSVDataset):
     """
-    Implements extra properties of vein files for the UTFVP database
-
-
-    Parameters:
-
-        f (object): Low-level file (or sample) object that is kept inside
-
+    The University of Twente Finger Vascular Pattern dataset
     """
 
-    def __init__(self, f):
-
-        super(File, self).__init__(client_id=f.unique_finger_name, path=f.path,
-            file_id=f.id)
-        self.__f = f
-
-
-    def load(self, *args, **kwargs):
-        """(Overrides base method) Loads both image and mask"""
-
-        image = super(File, self).load(*args, **kwargs)
-        roi = self.__f.roi()
-        return AnnotatedArray(image, metadata=dict(roi=roi))
-
-
-class Database(BioDatabase):
-    """
-    Implements verification API for querying UTFVP database.
-    """
-
-    def __init__(self, **kwargs):
-
-        super(Database, self).__init__(name='utfvp', **kwargs)
-        from bob.db.utfvp.query import Database as LowLevelDatabase
-        self._db = LowLevelDatabase()
-
-        self.low_level_group_names = ('train', 'dev', 'eval')
-        self.high_level_group_names = ('world', 'dev', 'eval')
-
-    def groups(self):
-
-        return self.convert_names_to_highlevel(self._db.groups(),
-            self.low_level_group_names, self.high_level_group_names)
-
-    def client_id_from_model_id(self, model_id, group='dev'):
-        """Required as ``model_id != client_id`` on this database"""
-
-        return self._db.finger_name_from_model_id(model_id)
-
-
-    def model_ids_with_protocol(self, groups=None, protocol=None, **kwargs):
-
-        groups = self.convert_names_to_lowlevel(groups,
-            self.low_level_group_names, self.high_level_group_names)
-        return self._db.model_ids(groups=groups, protocol=protocol)
-
-
-    def objects(self, groups=None, protocol=None, purposes=None,
-                model_ids=None, **kwargs):
-
-        groups = self.convert_names_to_lowlevel(groups,
-            self.low_level_group_names, self.high_level_group_names)
-        retval = self._db.objects(groups=groups, protocol=protocol,
-                                  purposes=purposes, model_ids=model_ids,
-                                  **kwargs)
-
-        return [File(f) for f in retval]
-
-
-    def annotations(self, file):
-        return None
+    def __init__(self, protocol):
+        # Downloading model if not exists
+        urls = UtfvpDatabase.urls()
+        filename = get_file(
+            "utfvp_csv.tar.gz",
+            urls,
+            file_hash="0b22a4ea6a78d54879dc3d866a22108b7513d169cd5c1bceb044854a871f200a",
+        )
+
+        super().__init__(
+            name="utfvp",
+            dataset_protocol_path=filename,
+            protocol=protocol,
+            csv_to_sample_loader=CSVToSampleLoaderBiometrics(
+                data_loader=bob.io.image.load,
+                dataset_original_directory=rc.get(
+                    "bob.bio.vein.utfvp.directory", ""
+                ),
+                extension='',
+                reference_id_equal_subject_id=False
+            ),
+            allow_scoring_with_all_biometric_references=True,
+        )
+
+    @staticmethod
+    def protocols():
+        # TODO: Until we have (if we have) a function that dumps the protocols, let's use this one.
+        return ["nom", "full", "1vsall",
+                "nomLeftRing", "nomRightRing", "nomLeftMiddle", "nomRightMiddle", "nomLeftIndex", "nomRightIndex",
+                "fullLeftRing", "fullRightRing", "fullLeftMiddle", "fullRightMiddle", "fullLeftIndex", "fullRightIndex"]
+
+    @staticmethod
+    def urls():
+        return ["https://www.idiap.ch/software/bob/databases/latest/utfvp_csv-0b22a4ea.tar.gz",
+                "http://www.idiap.ch/software/bob/databases/latest/utfvp_csv-0b22a4ea.tar.gz",
+                ]
diff --git a/bob/bio/vein/tests/test_databases.py b/bob/bio/vein/tests/test_databases.py
index d665d2710d2c4a1b8589d9155b546a106b23be27..7e07010412fe80601a8d2085521fe28a371ccaef 100644
--- a/bob/bio/vein/tests/test_databases.py
+++ b/bob/bio/vein/tests/test_databases.py
@@ -7,27 +7,154 @@ from nose.plugins.skip import SkipTest
 import bob.bio.base
 from bob.bio.base.test.utils import db_available
 from bob.bio.base.test.test_database_implementations import check_database
+import os
+from bob.extension.download import get_file
 
 
-@db_available('utfvp')
 def test_utfvp():
-    module = bob.bio.base.load_resource('utfvp', 'config',
-        preferred_package='bob.bio.vein')
+    from bob.bio.vein.database.utfvp import UtfvpDatabase
+
+    # Getting the absolute path
+    urls = UtfvpDatabase.urls()
+    filename = get_file("utfvp_csv.tar.gz", urls)
+
+    # Removing the file before the test
     try:
-        check_database(module.database, protocol='nomLeftIndex', groups=('dev',
-          'eval'))
-    except IOError as e:
-        raise SkipTest(
-            "The database could not queried; probably the db.sql3 file is missing. Here is the error: '%s'" % e)
+        os.remove(filename)
+    except Exception:
+        pass
+
+    N_SUBJECTS, N_FINGERS, N_SESSIONS = 60, 6, 4
+    # nom
+    nom_parameters = {'N_train': 10,
+                      'N_dev': 18,
+                      'N_eval': 32,
+                      'N_session': N_SESSIONS // 2,
+                      'N_session_training': N_SESSIONS,
+                      'N_fingers': 6,
+                      'N_fingers_training': 6,
+                      }
+    # full
+    full_parameters = {'N_train': 0,
+                       'N_dev': N_SUBJECTS,
+                       'N_eval': 0,
+                       'N_session': N_SESSIONS,
+                       'N_fingers': 6,
+                       }
+
+    # 1vsall
+    onevsall_parameters = {'N_train': 35,
+                           'N_dev': 65,
+                           'N_eval': 0,
+                           'N_session': N_SESSIONS,
+                           'N_session_training': N_SESSIONS,
+                           'N_fingers': 5,
+                           'N_fingers_training': 1,
+                           }
+    # subnom
+    subnom_parameters = {'N_train': 10,
+                         'N_dev': 18,
+                         'N_eval': 32,
+                         'N_session': N_SESSIONS // 2,
+                         'N_session_training': N_SESSIONS,
+                         'N_fingers': 1,
+                         'N_fingers_training': 1,
+                         }
+
+    # subfull
+    subfull_parameters = {'N_train': 0,
+                          'N_dev': N_SUBJECTS,
+                          'N_eval': 0,
+                          'N_session': N_SESSIONS,
+                          'N_fingers': 1,
+                          }
+
+    protocols_parameters = {'nom': nom_parameters,
+                            'full': full_parameters,
+                            '1vsall': onevsall_parameters,
+                            'subnom': subnom_parameters,
+                            'subfull': subfull_parameters,
+                            }
+
+    def _check_protocol(p, parameters, train=False, eval=False):
+        database = UtfvpDatabase(protocol=p)
+
+        if train:
+            assert len(database.background_model_samples()) == \
+                   parameters['N_train'] * parameters['N_fingers_training'] * parameters['N_session_training']
+
+        assert len(database.references(group="dev")) == \
+               parameters['N_dev'] * parameters['N_fingers'] * parameters['N_session']
+        assert len(database.probes(group="dev")) == \
+               parameters['N_dev'] * parameters['N_fingers'] * parameters['N_session']
+
+        if eval:
+            assert len(database.references(group="eval")) == \
+                   parameters['N_eval'] * parameters['N_fingers'] * parameters['N_session']
+            assert len(database.probes(group="eval")) == \
+                   parameters['N_eval'] * parameters['N_fingers'] * parameters['N_session']
+
+        return p
+
+    checked_protocols = []
+
+    checked_protocols.append(
+        _check_protocol("nom", protocols_parameters['nom'], train=True, eval=True)
+    )
+    checked_protocols.append(
+        _check_protocol("full", protocols_parameters['full'], train=False, eval=False)
+    )
+    checked_protocols.append(
+        _check_protocol("1vsall", protocols_parameters['1vsall'], train=True, eval=False)
+    )
+    checked_protocols.append(
+        _check_protocol("nomLeftIndex", protocols_parameters['subnom'], train=True, eval=True)
+    )
+    checked_protocols.append(
+        _check_protocol("nomLeftMiddle", protocols_parameters['subnom'], train=True, eval=True)
+    )
+    checked_protocols.append(
+        _check_protocol("nomLeftRing", protocols_parameters['subnom'], train=True, eval=True)
+    )
+    checked_protocols.append(
+        _check_protocol("nomRightIndex", protocols_parameters['subnom'], train=True, eval=True)
+    )
+    checked_protocols.append(
+        _check_protocol("nomRightMiddle", protocols_parameters['subnom'], train=True, eval=True)
+    )
+    checked_protocols.append(
+        _check_protocol("nomRightRing", protocols_parameters['subnom'], train=True, eval=True)
+    )
+    checked_protocols.append(
+        _check_protocol("fullLeftIndex", protocols_parameters['subfull'], train=False, eval=False)
+    )
+    checked_protocols.append(
+        _check_protocol("fullLeftMiddle", protocols_parameters['subfull'], train=False, eval=False)
+    )
+    checked_protocols.append(
+        _check_protocol("fullLeftRing", protocols_parameters['subfull'], train=False, eval=False)
+    )
+    checked_protocols.append(
+        _check_protocol("fullRightIndex", protocols_parameters['subfull'], train=False, eval=False)
+    )
+    checked_protocols.append(
+        _check_protocol("fullRightMiddle", protocols_parameters['subfull'], train=False, eval=False)
+    )
+    checked_protocols.append(
+        _check_protocol("fullRightRing", protocols_parameters['subfull'], train=False, eval=False)
+    )
+
+    for p in UtfvpDatabase.protocols():
+        assert p in checked_protocols, "Protocol {} untested".format(p)
 
 
 @db_available('verafinger')
 def test_verafinger():
     module = bob.bio.base.load_resource('verafinger', 'config',
-        preferred_package='bob.bio.vein')
+                                        preferred_package='bob.bio.vein')
     try:
         check_database(module.database, protocol='Fifty', groups=('dev',
-          'eval'))
+                                                                  'eval'))
     except IOError as e:
         raise SkipTest(
             "The database could not queried; probably the db.sql3 file is missing. Here is the error: '%s'" % e)
@@ -36,7 +163,7 @@ def test_verafinger():
 @db_available('fv3d')
 def test_fv3d():
     module = bob.bio.base.load_resource('fv3d', 'config',
-        preferred_package='bob.bio.vein')
+                                        preferred_package='bob.bio.vein')
     try:
         check_database(module.database, protocol='central', groups=('dev',))
     except IOError as e:
@@ -47,7 +174,7 @@ def test_fv3d():
 @db_available('putvein')
 def test_putvein():
     module = bob.bio.base.load_resource('putvein', 'config',
-        preferred_package='bob.bio.vein')
+                                        preferred_package='bob.bio.vein')
     try:
         check_database(module.database, protocol='wrist-LR_1', groups=('dev',))
     except IOError as e:
diff --git a/setup.py b/setup.py
index fbbe5a436ac65f84cedbffc656f40a2860e7bd45..a31d06f586a5c933b6dfc705a8316cadd1c73475 100644
--- a/setup.py
+++ b/setup.py
@@ -32,9 +32,9 @@ setup(
             "Full = bob.bio.vein.config.database.protocol_verafinger.full",
             "Cropped-Full = bob.bio.vein.config.database.protocol_verafinger.cropped_full",
             # utfvp
-            "nom = bob.bio.vein.config.database.protocol_utfvp.nom",
-            "full = bob.bio.vein.config.database.protocol_utfvp.full",
-            "1vsall = bob.bio.vein.config.database.protocol_utfvp.one_vs_all",
+            "nom = bob.bio.vein.config.database.utfvp_nom",
+            "full = bob.bio.vein.config.database.utfvp_full",
+            "1vsall = bob.bio.vein.config.database.utfvp_1vsall",
             # fv3d
             "central = bob.bio.vein.config.database.protocol_fv3d.central",
             "left = bob.bio.vein.config.database.protocol_fv3d.left",
@@ -47,7 +47,6 @@ setup(
             "palm-LR-4 = bob.bio.vein.config.database.protocol_putvein.palm_lr_4",
             # legacy databases
             "verafinger = bob.bio.vein.config.database.verafinger",
-            "utfvp = bob.bio.vein.config.database.utfvp",
             "fv3d = bob.bio.vein.config.database.fv3d",
             "putvein = bob.bio.vein.config.database.putvein",
             # legacy baselines
@@ -57,7 +56,7 @@ setup(
         ],
         "bob.bio.database": [
             "verafinger = bob.bio.vein.config.database.verafinger:database",
-            "utfvp = bob.bio.vein.config.database.utfvp:database",
+            "utfvp = bob.bio.vein.config.database.utfvp_nom:database",
             "fv3d = bob.bio.vein.config.database.fv3d:database",
             "putvein = bob.bio.vein.config.database.putvein:database",
         ],