diff --git a/configValidation.js b/configValidation.js
new file mode 100644
index 000000000..eca2f84a8
--- /dev/null
+++ b/configValidation.js
@@ -0,0 +1,26 @@
+'use strict';
+
+const Joi = require('joi');
+
+// Schema Configuration
+// datapath: string (required)
+// files: array of strings
+// deduplicate: boolean
+// adminLookup: boolean
+const schema = Joi.object().keys({
+  files: Joi.array().items(Joi.string()),
+  datapath: Joi.string(),
+  deduplicate: Joi.boolean(),
+  adminLookup: Joi.boolean()
+}).requiredKeys('datapath').unknown(false);
+
+module.exports = {
+  validate: function validate(config) {
+    Joi.validate(config, schema, (err) => {
+      if (err) {
+        throw new Error(err.details[0].message);
+      }
+    });
+  }
+
+};
diff --git a/import.js b/import.js
index 95aebd637..329ad03b8 100644
--- a/import.js
+++ b/import.js
@@ -5,6 +5,9 @@
 'use strict';
 
 var peliasConfig = require( 'pelias-config' ).generate();
+
+require('./configValidation').validate(peliasConfig);
+
 var logger = require( 'pelias-logger' ).get( 'openaddresses' );
 
 var parameters = require( './lib/parameters' );
diff --git a/package.json b/package.json
index 93c107dd3..508394eb4 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
     "combined-stream": "1.0.5",
     "csv-parse": "^1.1.7",
     "glob": "^7.0.0",
+    "joi": "^10.1.0",
     "lodash": "^4.10.0",
     "minimist": "1.2.0",
     "pelias-address-deduplicator": "1.1.0",
@@ -28,6 +29,7 @@
     "event-stream": "^3.3.2",
     "jshint": "^2.9.4",
     "precommit-hook": "3.0.0",
+    "proxyquire": "^1.7.10",
     "tap-spec": "4.1.1",
     "tape": "^4.5.0",
     "temp": "^0.8.3",
diff --git a/test/configValidation.js b/test/configValidation.js
new file mode 100644
index 000000000..7662cdcbe
--- /dev/null
+++ b/test/configValidation.js
@@ -0,0 +1,130 @@
+'use strict';
+
+const tape = require( 'tape' );
+
+const configValidation = require( '../configValidation' );
+
+tape( 'missing datapath should throw error', function(test) {
+  const config = {};
+
+  test.throws(() => {
+    configValidation.validate(config);
+  }, /"datapath" is required/);
+
+  test.end();
+});
+
+tape( 'non-string datapath should throw error', function(test) {
+  [null, 17, {}, [], false].forEach((value) => {
+    const config = {
+      datapath: value
+    };
+
+    test.throws(() => {
+      configValidation.validate(config);
+    }, /"datapath" must be a string/);
+
+  });
+
+  test.end();
+});
+
+tape( 'non-array files should throw error', function(test) {
+  [null, 17, {}, 'string', false].forEach((value) => {
+    const config = {
+      datapath: 'this is the datapath',
+      files: value
+    };
+
+    test.throws(() => {
+      configValidation.validate(config);
+    }, /"files" must be an array/, 'datapath is required');
+  });
+
+  test.end();
+});
+
+tape( 'non-string elements in files array should throw error', function(test) {
+  [null, 17, {}, [], false].forEach((value) => {
+    const config = {
+      datapath: 'this is the datapath',
+      files: [value]
+    };
+
+    test.throws(() => {
+      configValidation.validate(config);
+    }, /"0" must be a string/, 'files elements must be strings');
+  });
+
+  test.end();
+});
+
+tape( 'non-boolean adminLookup should throw error', function(test) {
+  [null, 17, {}, [], 'string'].forEach((value) => {
+    const config = {
+      datapath: 'this is the datapath',
+      adminLookup: value
+    };
+
+    test.throws(() => {
+      configValidation.validate(config);
+    }, /"adminLookup" must be a boolean/);
+  });
+
+  test.end();
+});
+
+tape( 'non-boolean deduplicate should throw error', function(test) {
+  [null, 17, {}, [], 'string'].forEach((value) => {
+    const config = {
+      datapath: 'this is the datapath',
+      deduplicate: value
+    };
+
+    test.throws(() => {
+      configValidation.validate(config);
+    }, /"deduplicate" must be a boolean/);
+  });
+
+  test.end();
+});
+
+tape( 'unknown config fields should throw error', function(test) {
+  const config = {
+    datapath: 'this is the datapath',
+    unknown: 'value'
+  };
+
+  test.throws(() => {
+    configValidation.validate(config);
+  }, /"unknown" is not allowed/, 'unknown fields should be disallowed');
+  test.end();
+
+});
+
+tape( 'configuration with only datapath should not throw error', function(test) {
+  const config = {
+    datapath: 'this is the datapath'
+  };
+
+  test.doesNotThrow(() => {
+    configValidation.validate(config);
+  }, 'config should be valid');
+  test.end();
+
+});
+
+tape( 'valid configuration should not throw error', function(test) {
+  const config = {
+    datapath: 'this is the datapath',
+    deduplicate: false,
+    adminLookup: false,
+    files: ['file 1', 'file 2']
+  };
+
+  test.doesNotThrow(() => {
+    configValidation.validate(config);
+  }, 'config should be valid');
+  test.end();
+
+});
diff --git a/test/import.js b/test/import.js
new file mode 100644
index 000000000..9e2591165
--- /dev/null
+++ b/test/import.js
@@ -0,0 +1,21 @@
+'use strict';
+
+const tape = require( 'tape' );
+
+const proxyquire = require('proxyquire').noCallThru();
+
+tape( 'configValidation throwing error should rethrow', function(test) {
+  test.throws(function() {
+    proxyquire('../import', {
+      './configValidation': {
+        validate: () => {
+          throw Error('config is not valid');
+        }
+      }
+    })();
+
+  }, /config is not valid/);
+
+  test.end();
+
+});
diff --git a/test/test.js b/test/test.js
index f180ada42..72111d640 100644
--- a/test/test.js
+++ b/test/test.js
@@ -4,8 +4,10 @@
 
 'use strict';
 
+require( './configValidation' );
 require( './isValidCsvRecord' );
 require( './streams/adminLookupStream');
+require( './import');
 require( './importPipeline');
 require( './parameters' );
 require( './streams/cleanupStream' );