diff --git a/src/mrmc.cpp b/src/mrmc.cpp
index 179877e78..243f1e0cc 100644
--- a/src/mrmc.cpp
+++ b/src/mrmc.cpp
@@ -87,11 +87,6 @@ int main(const int argc, const char* argv[]) {
 		delete s;
 		return 0;
 	}
-	if (s->isSet("help-config")) {
-		std::cout << mrmc::settings::helpConfigfile;
-		delete s;
-		return 0;
-	}
 	if (s->isSet("test-prctl")) {
 		mrmc::parser::PRCTLParser parser(s->getString("test-prctl").c_str());
 		delete s;
diff --git a/src/utility/settings.cpp b/src/utility/settings.cpp
index 429ffa6a9..748bc931a 100644
--- a/src/utility/settings.cpp
+++ b/src/utility/settings.cpp
@@ -11,6 +11,8 @@
 #include "log4cplus/loggingmacros.h"
 extern log4cplus::Logger logger;
 
+#include <boost/algorithm/string/join.hpp>
+
 namespace mrmc {
 namespace settings {
 
@@ -19,11 +21,12 @@ namespace bpo = boost::program_options;
 /*
  * static initializers
  */
-std::unique_ptr<bpo::options_description> mrmc::settings::Settings::cli;
-std::unique_ptr<bpo::options_description> mrmc::settings::Settings::conf = nullptr;
+std::unique_ptr<bpo::options_description> mrmc::settings::Settings::desc = nullptr;
 std::string mrmc::settings::Settings::binaryName = "";
 mrmc::settings::Settings* mrmc::settings::Settings::inst = nullptr;
 
+std::map< std::pair<std::string, std::string>, bpo::options_description* > mrmc::settings::Settings::modules;
+
 /*!
  *	The constructor fills the option descriptions, parses the
  *	command line and the config file and puts the option values to
@@ -38,46 +41,63 @@ mrmc::settings::Settings* mrmc::settings::Settings::inst = nullptr;
  *	@param filename	either nullptr or name of config file
  */
 Settings::Settings(const int argc, const char* argv[], const char* filename)
-	: configfile("Config Options"), generic("Generic Options"), commandline("Commandline Options")
 {
 	Settings::binaryName = std::string(argv[0]);
 	try
 	{
-		//! Initially fill description objects and call register callbacks
+		// Initially fill description objects
 		this->initDescriptions();
 
-		//! Take care of positional arguments
+		// Take care of positional arguments
 		Settings::positional.add("trafile", 1);
 		Settings::positional.add("labfile", 1);
+
+		// Check module triggers, add corresponding options
+		std::map< std::string, std::list< std::string > > options;
 		
-		//! Create and fill collecting options descriptions
-		Settings::cli = std::unique_ptr<bpo::options_description>(new bpo::options_description());
-		Settings::cli->add(Settings::commandline).add(generic);
-		Settings::conf = std::unique_ptr<bpo::options_description>(new bpo::options_description());
-		Settings::conf->add(Settings::configfile).add(generic);
+		for (auto it : Settings::modules)
+		{
+			options[it.first.first].push_back(it.first.second);
+		}
+		for (auto it : options)
+		{
+			std::stringstream str;
+			str << "select " << it.first << " module (" << boost::algorithm::join(it.second, ", ") << ")";
+			
+			Settings::desc->add_options()
+				(it.first.c_str(), bpo::value<std::string>(), str.str().c_str())
+			;
+		}
 		
-		//! Perform first parse run and call intermediate callbacks
+		// Perform first parse run
 		this->firstRun(argc, argv, filename);
 		
-		//! Rebuild collecting options descriptions
-		Settings::cli = std::unique_ptr<bpo::options_description>(new bpo::options_description());
-		Settings::cli->add(Settings::commandline).add(generic);
-
-		Settings::conf = std::unique_ptr<bpo::options_description>(new bpo::options_description());
-		Settings::conf->add(Settings::configfile).add(generic);
+		// Check module triggers
+		for (auto it : Settings::modules)
+		{
+			std::pair< std::string, std::string > trigger = it.first;
+			if (this->vm.count(trigger.first))
+			{
+				if (this->vm[trigger.first].as<std::string>().compare(trigger.second) == 0)
+				{
+					Settings::desc->add(*it.second);
+					Settings::modules.erase(trigger);
+				}
+			}
+			
+		}
 		
-		//! Stop if help is set
-		if ((this->vm.count("help") > 0) || (this->vm.count("help-config") > 0))
+		// Stop if help is set
+		if (this->vm.count("help") > 0)
 		{
 			return;
 		}
 		
-		//! Perform second run and call checker callbacks
+		// Perform second run
 		this->secondRun(argc, argv, filename);
 		
-		//! Finalize parsed options, check for specified requirements
+		// Finalize parsed options, check for specified requirements
 		bpo::notify(this->vm);
-		mrmc::settings::Callbacks::instance()->disabled = true;
 		LOG4CPLUS_DEBUG(logger, "Finished loading config.");
 	}
 	catch (bpo::reading_file e)
@@ -118,100 +138,38 @@ Settings::Settings(const int argc, const char* argv[], const char* filename)
 void Settings::initDescriptions()
 {
 	LOG4CPLUS_DEBUG(logger, "Initializing descriptions.");
-	this->commandline.add_options()
+	Settings::desc = std::unique_ptr<bpo::options_description>(new bpo::options_description("Generic Options"));
+	Settings::desc->add_options()
 		("help,h", "produce help message")
 		("verbose,v", "be verbose")
-		("help-config", "produce help message about config file")
 		("configfile,c", bpo::value<std::string>(), "name of config file")
 		("test-prctl", bpo::value<std::string>(), "name of prctl file")
-	;
-	this->generic.add_options()
 		("trafile", bpo::value<std::string>()->required(), "name of the .tra file")
 		("labfile", bpo::value<std::string>()->required(), "name of the .lab file")
 	;
-	this->configfile.add_options()
-	;
-
-	/*
-	 *	Get Callbacks object, then iterate over and call all register callbacks.
-	 */
-	Callbacks* cb = mrmc::settings::Callbacks::instance();
-	while (cb->registerList.size() > 0)
-	{
-		CallbackType type = cb->registerList.front().first;
-		RegisterCallback fptr = cb->registerList.front().second;
-		cb->registerList.pop_front();
-		
-		switch (type)
-		{
-			case CB_CONFIG:
-				(*fptr)(this->configfile);
-				break;
-			case CB_CLI:
-				(*fptr)(this->commandline);
-				break;
-			case CB_GENERIC:
-				(*fptr)(this->generic);
-				break;
-		}
-	}
 }
 
 /*!
  *	Perform a sloppy parsing run: parse command line and config file (if
  *	given), but allow for unregistered options, do not check requirements
  *	from options_description objects, do not check positional arguments.
- *
- *	Call all intermediate callbacks afterwards.
  */
 void Settings::firstRun(const int argc, const char* argv[], const char* filename)
 {
 	LOG4CPLUS_DEBUG(logger, "Performing first run.");
-	//! parse command line
-	bpo::store(bpo::command_line_parser(argc, argv).options(*(Settings::cli)).allow_unregistered().run(), this->vm);
+	// parse command line
+	bpo::store(bpo::command_line_parser(argc, argv).options(*(Settings::desc)).allow_unregistered().run(), this->vm);
 
 	/*
 	 *	load config file if specified
 	 */
 	if (this->vm.count("configfile"))
 	{
-		bpo::store(bpo::parse_config_file<char>(this->vm["configfile"].as<std::string>().c_str(), *(Settings::conf)), this->vm, true);
+		bpo::store(bpo::parse_config_file<char>(this->vm["configfile"].as<std::string>().c_str(), *(Settings::desc)), this->vm, true);
 	}
 	else if (filename != NULL)
 	{
-		bpo::store(bpo::parse_config_file<char>(filename, *(Settings::conf)), this->vm, true);
-	}
-	
-	/*
-	 *	Call intermediate callbacks.
-	 */
-	Callbacks* cb = mrmc::settings::Callbacks::instance();
-	while (cb->intermediateList.size() > 0)
-	{
-		CallbackType type = cb->intermediateList.front().first;
-		IntermediateCallback fptr = cb->intermediateList.front().second;
-		cb->intermediateList.pop_front();
-		
-		try
-		{
-			switch (type)
-			{
-				case CB_CONFIG:
-					(*fptr)(&this->configfile, this->vm);
-					break;
-				case CB_CLI:
-					(*fptr)(&this->commandline, this->vm);
-					break;
-				case CB_GENERIC:
-					(*fptr)(&this->generic, this->vm);
-					break;
-			}
-		}
-		catch (boost::bad_any_cast e)
-		{
-			std::cerr << "An intermediate callback failed." << std::endl;
-			LOG4CPLUS_ERROR(logger, "An intermediate callback failed.\n" << e.what());
-		}
+		bpo::store(bpo::parse_config_file<char>(filename, *(Settings::desc)), this->vm, true);
 	}
 }
 
@@ -219,42 +177,22 @@ void Settings::firstRun(const int argc, const char* argv[], const char* filename
  *	Perform the second parser run: parse command line and config file (if
  *	given) and check for unregistered options, requirements from
  *	options_description objects and positional arguments.
- *
- *	Call all checker callbacks afterwards.
  */
 void Settings::secondRun(const int argc, const char* argv[], const char* filename)
 {
 	LOG4CPLUS_DEBUG(logger, "Performing second run.");
-	//! Parse command line
-	bpo::store(bpo::command_line_parser(argc, argv).options(*(Settings::cli)).positional(this->positional).run(), this->vm);
+	// Parse command line
+	bpo::store(bpo::command_line_parser(argc, argv).options(*(Settings::desc)).positional(this->positional).run(), this->vm);
 	/*
 	 *	load config file if specified
 	 */
 	if (this->vm.count("configfile"))
 	{
-		bpo::store(bpo::parse_config_file<char>(this->vm["configfile"].as<std::string>().c_str(), *(Settings::conf)), this->vm, true);
+		bpo::store(bpo::parse_config_file<char>(this->vm["configfile"].as<std::string>().c_str(), *(Settings::desc)), this->vm, true);
 	}
 	else if (filename != NULL)
 	{
-		bpo::store(bpo::parse_config_file<char>(filename, *(Settings::conf)), this->vm, true);
-	}
-	
-	
-	/*
-	 *	Call checker callbacks.
-	 */
-	Callbacks* cb = mrmc::settings::Callbacks::instance();
-	while (cb->checkerList.size() > 0)
-	{
-		CheckerCallback fptr = cb->checkerList.front();
-		cb->checkerList.pop_front();
-		
-		if (! (*fptr)(this->vm))
-		{
-			std::cerr << "Custom option checker failed." << std::endl;
-			LOG4CPLUS_ERROR(logger, "A checker callback returned false.");
-			throw mrmc::exceptions::InvalidSettings();
-		}
+		bpo::store(bpo::parse_config_file<char>(filename, *(Settings::desc)), this->vm, true);
 	}
 }
 
@@ -269,19 +207,11 @@ void Settings::secondRun(const int argc, const char* argv[], const char* filenam
 std::ostream& help(std::ostream& os)
 {
 	os << "Usage: " << mrmc::settings::Settings::binaryName << " [options] <transition file> <label file>" << std::endl;
-	os << *(mrmc::settings::Settings::cli) << std::endl;
-	return os;
-}
-
-/*!
- *	Print a list of available options for the config file.
- *
- *	Use it like this:
- *	@code std::cout << mrmc::settings::helpConfigfile; @endcode
- */
-std::ostream& helpConfigfile(std::ostream& os)
-{
-	os << *(mrmc::settings::Settings::conf) << std::endl;;
+	os << *(mrmc::settings::Settings::desc) << std::endl;
+	for (auto it : Settings::modules)
+	{
+		os << *(it.second) << std::endl;
+	}
 	return os;
 }
 
diff --git a/src/utility/settings.h b/src/utility/settings.h
index 08e56736d..842074655 100644
--- a/src/utility/settings.h
+++ b/src/utility/settings.h
@@ -9,6 +9,7 @@
 #define SETTINGS_H_
 
 #include <iostream>
+#include <sstream>
 #include <list>
 #include <utility>
 #include <memory>
@@ -25,14 +26,9 @@ namespace mrmc {
 namespace settings {
 	
 	namespace bpo = boost::program_options;
-	/*
-	 *	Sorry for very long comment at this point (for the class), but all
-	 *	methods are private, hence there is no other place to explain the
-	 *	inner workings of this class that are necessary to understand the
-	 *	callback concept...
-	 */
+	
 	/*!
-	 *	@brief	Simple wrapper around boost::program_options to handle configuration options.
+	 *	@brief	Wrapper around boost::program_options to handle configuration options.
 	 *
 	 *	This class uses boost::program_options to read options from the
 	 *	commandline and additionally load options from a file.
@@ -44,36 +40,15 @@ namespace settings {
 	 *	@code mrmc::settings::instance() @endcode
 	 *
 	 *	This class can be customized by other parts of the software using
-	 *	callbacks. There are three types of callbacks: register,
-	 *	intermediate and checker.
-	 *
-	 *	The (private) constructor will start with filling the internal
-	 *	options_description object. There are a few generic options like
-	 *	--help or --verbose. Then if calls all register callbacks that may
-	 *	add more options.
-	 *
-	 *	Then, it will start with a sloppy parsing run, allowing unregistered 
-	 *	options and ignoring further constraints from the options_description 
-	 *	objects.
-	 *
-	 *	After that, it will call all intermediate callbacks. They can
-	 *	inspect the options from the first run and add more options, e.g.
-	 *	enable more options for a specific component that has been enabled.
-	 *
-	 *	Using the new options_description objects, the constructor performs
-	 *	a second run. This time, it will not allow unregistered options and
-	 *	will check for required and positional arguments.
-	 *
-	 *	Finally, all checker callbacks will be called. They can check the
-	 *	final options for more complex requirements. If any of those checker
-	 *	callbacks returns false, a InvalidSettings exception will be thrown.
+	 *	option modules. An option module can be anything that implements the
+	 *	interface specified by registerModule().
 	 */
 	class Settings
 	{
 		public:
 		
 			/*!
-			 *	@brief Get value of a generic option.
+			 *	@brief	Get value of a generic option.
 			 */
 			template <typename T>
 			const T& get(const std::string &name) const {
@@ -82,18 +57,68 @@ namespace settings {
 			}
 		
 			/*!
-			 *	@brief Get value of string option
+			 *	@brief	Get value of string option
 			 */
 			const std::string& getString(const std::string &name) const {
 				return this->get<std::string>(name);
 			}
 		
 			/*!
-			 *	@brief Check if an option is set
+			 *	@brief	Check if an option is set
 			 */
 			const bool isSet(const std::string &name) const {
 				return this->vm.count(name) > 0;
 			}
+			
+			/*!
+			 *	@brief	Register a new module.
+			 *
+			 *	A new settings module can be registered via
+			 *	@code
+			 *	mrmc::settings::Settings::registerModule<mrmc::ModuleClass>();
+			 *	@endcode
+			 *	This has to be done before any parsing takes place, i.e. before newInstance() is called.
+			 *
+			 *	This function implicitly defines the following interface for any SettingsModule:
+			 *	@code
+			 *	static std::string getModuleName();
+			 *	static std::pair< std::string, std::string > getOptionTrigger();
+			 *	static void putOptions(boost::program_options::options_description*);
+			 *	@endcode
+			 *
+			 *	The semantic is the following:
+			 *	If the trigger <a,b> is true, i.e. if option a is set to b,
+			 *	the options_description object will be added to the internal
+			 *	option object.
+			 *
+			 *	Furthermore, it will generate the option specified by the
+			 *	trigger.
+			 *
+			 *	The functions could look like this:
+			 *	@code
+			 *	static std::string getModuleName() { return "Backend A"; }
+			 *	static std::pair<std::string, std::string> getOptionTrigger() {
+			 *		return std::pair<std::string, std::string>("backend", "a");
+			 *	}
+			 *	static void putOptions(boost::program_options::options_description* desc) {
+			 *		desc->add_options()("foo", "bar");
+			 *	}
+			 *	@endcode
+			 */
+			template <typename T>
+			static void registerModule()
+			{
+				// get trigger
+				std::pair< std::string, std::string > trigger = T::getOptionTrigger();
+				// build description name
+				std::stringstream str;
+				str << T::getModuleName() << " (" << trigger.first << " = " << trigger.second << ")";
+				bpo::options_description* desc = new bpo::options_description(str.str());
+				// but options
+				T::putOptions(desc);
+				// store
+				Settings::modules[ trigger ] = desc;
+			}
 	
 			friend std::ostream& help(std::ostream& os);
 			friend std::ostream& helpConfigfile(std::ostream& os);
@@ -121,31 +146,20 @@ namespace settings {
 			 */
 			void secondRun(const int argc, const char* argv[], const char* filename);
 			
-			/*!
-			 *	@brief	Option descriptions for config file.
-			 */
-			bpo::options_description configfile;
-			/*!
-			 *	@brief	Option descriptions for config file and command line.
-			 */
-			bpo::options_description generic;
-			/*!
-			 *	@brief	Option descriptions for command line.
-			 */
-			bpo::options_description commandline;
 			/*!
 			 *	@brief	Option description for positional arguments on command line.
 			 */
 			bpo::positional_options_description positional;
 			
 			/*!
-			 *	@brief	Collecting option descriptions for command line.
+			 *	@brief	Collecting option descriptions.
 			 */
-			static std::unique_ptr<bpo::options_description> cli;
+			static std::unique_ptr<bpo::options_description> desc;
+
 			/*!
-			 *	@brief	Collecting option descriptions for config file.
+			 *	@brief	Contains option descriptions for all modules.
 			 */
-			static std::unique_ptr<bpo::options_description> conf;
+			static std::map< std::pair< std::string, std::string >, bpo::options_description* > modules;
 			
 			/*!
 			 *	@brief	option mapping.
@@ -160,7 +174,7 @@ namespace settings {
 			/*!
 			 *	@brief	actual instance of this class.
 			 */
-			static Settings* inst;
+ 			static Settings* inst;
 	};
 
 	/*!
@@ -168,11 +182,6 @@ namespace settings {
 	 */
 	std::ostream& help(std::ostream& os);
 	
-	/*!
-	 *	@brief	Print help for config file options.
-	 */
-	std::ostream& helpConfigfile(std::ostream& os);
-	
 	/*!
 	 *	@brief	Return current instance.
 	 *
@@ -199,195 +208,7 @@ namespace settings {
 		Settings::inst = new Settings(argc, argv, filename);
 		return Settings::inst;
 	}
-	
-	/*!
-	 *	@brief	Function type for functions registering new options.
-	 */
-	typedef void(*RegisterCallback)(bpo::options_description&);
-	
-	/*!
-	 *	@brief	Function type for functions changing the parser state
-	 *	between the first and second run.
-	 */
-	typedef void(*IntermediateCallback)(bpo::options_description*, bpo::variables_map&);
-	
-	/*!
-	 *	@brief	Function type for function checking constraints on settings.
-	 */
-	typedef bool(*CheckerCallback)(bpo::variables_map&);
-	
-	/*!
-	 *	@brief	This enums specifies the three types of options.
-	 */
-	enum CallbackType {
-		//! Option can be set in config file
-		CB_CONFIG,
-		//! Option can be set on command line
-		CB_CLI, 
-		//! Option can be set in config file and command line
-		CB_GENERIC
-	};
-	
-	/*!
-	 *	@brief This class handles callbacks for registering new options and
-	 *	checking constraints on them afterwards.
-	 *
-	 *	As it should never be used directly, but only through the Register
-	 *	class, it does not provide any public methods.
-	 *
-	 *	This class is also a singleton (like Settings) and is implemented much
-	 *	simpler as we don't need any custom initialization code.
-	 */
-	class Callbacks
-	{
-		public:
-			inline void put(const CallbackType type, const RegisterCallback ptr)
-			{
-				if (this->disabled) throw mrmc::exceptions::InvalidSettings();
-				this->registerList.push_back(std::pair<CallbackType, RegisterCallback>(type, ptr));
-			}
-			inline void put(const CallbackType type, const IntermediateCallback ptr)
-			{
-				if (this->disabled) throw mrmc::exceptions::InvalidSettings();
-				this->intermediateList.push_back(std::pair<CallbackType, IntermediateCallback>(type, ptr));
-			}
-			inline void put(const CheckerCallback ptr)
-			{
-				if (this->disabled) throw mrmc::exceptions::InvalidSettings();
-				this->checkerList.push_back(ptr);
-			}
-			
-		private:
-			/*!
-			 *	@brief	Stores register callbacks.
-			 */
-			std::list<std::pair<CallbackType, RegisterCallback>> registerList;
-			
-			/*!
-			 *	@brief	Stores intermediate callbacks.
-			 */
-			std::list<std::pair<CallbackType, IntermediateCallback>> intermediateList;
-			
-			/*!
-			 *	@brief	Stores check callbacks.
-			 */
-			std::list<CheckerCallback> checkerList;
-			
-			/*!
-			 *	@brief	Stores if we already loaded the settings.
-			 */
-			bool disabled;
-			
-			/*!
-			 *	@brief Private constructor.
-			 */
-			Callbacks() : disabled(false) {}
-			/*!
-			 *	@brief Private copy constructor.
-			 */
-			Callbacks(const Callbacks&) {}
-			/*!
-			 *	@brief Private destructor.
-			 */
-			~Callbacks() {}			
-
-			/*!
-			 *	@brief Returns current instance to create singleton.
-			 *	@return current instance
-			 */
-			inline static Callbacks* instance()
-			{
-				static Callbacks inst;
-				return &inst;
-			}
-		
-		/*!
-		 *	@brief Register class needs access to lists.
-		 */
-		friend class Register;
 		
-		/*!
-		 *	@brief Settings class need access to lists.
-		 */
-		friend class Settings;
-	};
-	
-	/*!
-	 *	@brief Wrapper class to allow for registering callbacks during
-	 *	static initialization.
-	 *
-	 *	To use this class, use the following includes:
-	 *	@code
-	 *	#include "src/utility/settings.h"
-	 *	#include <boost/program_options.hpp>
-	 *	namespace bpo = boost::program_options;	
-	 *	@endcode
-	 */
-	class Register
-	{
-		public:
-			/*!
-			 *	@brief Registers given function as register callback.
-			 *
-			 *	This constructor registers a callback routine that might add
-			 *	new options for the Settings class. It should be used like
-			 *	this:
-			 *	@code
-			 *	void register(bpo::options_description& desc) {
-			 *		// do something with desc here
-			 *	}
-			 *	mrmc::settings::Register reg(mrmc::settings::CB_CLI, &register);
-			 *	@endcode
-			 *	This code should be executed during static initialization, i.e.
-			 *	it should be somewhere in the cpp-file.
-			 */
-			Register(const CallbackType type, const RegisterCallback ptr)
-			{
-				mrmc::settings::Callbacks::instance()->put(type, ptr);
-			}
-			
-			/*!
-			 *	@brief Registers given function as intermediate callback.
-			 * 
-			 *	This constructor registers a callback routine that can check
-			 *	the option assignment after the first run and change the
-			 *	options description before the second run.
-			 *	It should be used like this:
-			 *	@code
-			 *	void intermediate(bpo::options_description& desc, bpo::variables_map& map) {
-			 *		// check contents of map and maybe change desc
-			 *	}
-			 *	mrmc::settings::Register reg(mrmc::settings::CB_CLI, &intermediate);
-			 *	@endcode
-			 *	This code should be executed during static initialization, i.e.
-			 *	it should be somewhere in the cpp-file.
-			 */
-			Register(const CallbackType type, const IntermediateCallback ptr)
-			{
-				mrmc::settings::Callbacks::instance()->put(type, ptr);
-			}
-
-			/*!
-			 *	@brief Registers given function as check callback.
-			 * 
-			 *	This constructor registers a callback routine that can check
-			 *	the option assignment after the Settings class has loaded
-			 *	them. It should be used like this:
-			 *	@code
-			 *	void check(bpo::variables_map& map) {
-			 *		// check contents of map
-			 *	}
-			 *	mrmc::settings::Register reg(&check);
-			 *	@endcode
-			 *	This code should be executed during static initialization, i.e.
-			 *	it should be somewhere in the cpp-file.
-			 */
-			Register(const CheckerCallback ptr)
-			{
-				mrmc::settings::Callbacks::instance()->put(ptr);
-			}
-	};
-	
 } // namespace settings
 } // namespace mrmc