diff --git a/.gitignore b/.gitignore
index b944f3b..ec5515d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
+.idea/
+
 docs/
 build/
-
-include/sql/*.h
+cmake-build-debug/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3223e1c..c1f96a6 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
 cmake_minimum_required (VERSION 3.7)
 project(controller
-        VERSION 0.3.7
+        VERSION 0.3.0
         LANGUAGES C)
 
 add_executable(controller src/main.c)
diff --git a/include/models/controller.h b/include/models/controller.h
index 10d5827..1cf4fad 100644
--- a/include/models/controller.h
+++ b/include/models/controller.h
@@ -3,6 +3,7 @@
 
 #include <uuid/uuid.h>
 #include <stdint.h>
+#include <lmdb.h>
 
 #include <config.h>
 #include <models/relay.h>
diff --git a/include/models/junction_relay_schedule.h b/include/models/junction_relay_schedule.h
index ebc0755..3a1eccb 100644
--- a/include/models/junction_relay_schedule.h
+++ b/include/models/junction_relay_schedule.h
@@ -10,7 +10,4 @@ junction_relay_schedule_remove_for_relay(int relay_id);
 int
 junction_relay_schedule_insert_weekdays(int relay_id, int *schedule_ids);
 
-int*
-junction_relay_schedule_get_relay_ids_with_schedule(int schedule_id);
-
 #endif /* CONTROLLER_MODELS_JUNCTION_RELAY_SCHEDULE_H */
diff --git a/include/models/relay.h b/include/models/relay.h
index 498ea30..6ffb258 100644
--- a/include/models/relay.h
+++ b/include/models/relay.h
@@ -3,6 +3,7 @@
 
 #include <stdint.h>
 #include <time.h>
+#include <lmdb.h>
 
 #include <constants.h>
 #include <models/schedule.h>
@@ -12,6 +13,7 @@ typedef struct
     int id;
     uint8_t number;
     int is_on;
+    int is_on_schedule;
     int pulse_timer;
     int sent_to_broker;
     char name[MAX_NAME_LENGTH + 1];
diff --git a/include/models/schedule.h b/include/models/schedule.h
index ae91e14..3455e4c 100644
--- a/include/models/schedule.h
+++ b/include/models/schedule.h
@@ -3,6 +3,7 @@
 
 #include <stdint.h>
 #include <uuid/uuid.h>
+#include <lmdb.h>
 
 #include <models/period.h>
 
@@ -11,7 +12,7 @@ typedef struct
     int id;
     uuid_t uid;
     uint8_t weekday;
-    uint16_t periods_count;
+    uint16_t length;
     period_t *periods;
 } schedule_t;
 
diff --git a/include/sql/migration_0.h b/include/sql/migration_0.h
new file mode 100644
index 0000000..fc2ea85
--- /dev/null
+++ b/include/sql/migration_0.h
@@ -0,0 +1,96 @@
+unsigned char sql_migration_0_sql[] = {
+  0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65,
+  0x20, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x73,
+  0x0a, 0x28, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x64, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50,
+  0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x0a, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41,
+  0x55, 0x54, 0x4f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, 0x4e, 0x54,
+  0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x75, 0x69, 0x64, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e,
+  0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, 0x2c, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x41, 0x52, 0x43,
+  0x48, 0x41, 0x52, 0x28, 0x31, 0x32, 0x38, 0x29, 0x2c, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x63, 0x6f, 0x6d, 0x6d, 0x61, 0x6e, 0x64, 0x5f, 0x70, 0x6f,
+  0x72, 0x74, 0x20, 0x20, 0x20, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45,
+  0x52, 0x0a, 0x29, 0x3b, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65,
+  0x20, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x72, 0x65, 0x6c, 0x61, 0x79,
+  0x73, 0x0a, 0x28, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x75, 0x6d, 0x62,
+  0x65, 0x72, 0x20, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c, 0x2c, 0x0a, 0x20, 0x20,
+  0x20, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x20, 0x20, 0x20, 0x56, 0x41,
+  0x52, 0x43, 0x48, 0x41, 0x52, 0x28, 0x31, 0x32, 0x38, 0x29, 0x0a, 0x29,
+  0x3b, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x74, 0x61,
+  0x62, 0x6c, 0x65, 0x20, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+  0x73, 0x0a, 0x28, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x69, 0x64, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x20, 0x4b, 0x45, 0x59, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x41, 0x55, 0x54, 0x4f, 0x49, 0x4e, 0x43, 0x52, 0x45, 0x4d, 0x45, 0x4e,
+  0x54, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x75, 0x69, 0x64, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4e, 0x4f, 0x54, 0x20,
+  0x4e, 0x55, 0x4c, 0x4c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x55, 0x4e, 0x49, 0x51, 0x55, 0x45, 0x2c,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x20, 0x20, 0x20,
+  0x20, 0x56, 0x41, 0x52, 0x43, 0x48, 0x41, 0x52, 0x28, 0x31, 0x32, 0x38,
+  0x29, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x70, 0x65, 0x72, 0x69, 0x6f,
+  0x64, 0x73, 0x20, 0x42, 0x4c, 0x4f, 0x42, 0x0a, 0x29, 0x3b, 0x0a, 0x0a,
+  0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x20, 0x74, 0x61, 0x62, 0x6c, 0x65,
+  0x20, 0x6a, 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x72, 0x65,
+  0x6c, 0x61, 0x79, 0x5f, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c, 0x65,
+  0x0a, 0x28, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x77, 0x65, 0x65, 0x6b, 0x64,
+  0x61, 0x79, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x53,
+  0x4d, 0x41, 0x4c, 0x4c, 0x49, 0x4e, 0x54, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x4e, 0x4f, 0x54, 0x20, 0x4e, 0x55, 0x4c, 0x4c,
+  0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x5f,
+  0x69, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x4e,
+  0x54, 0x45, 0x47, 0x45, 0x52, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x52, 0x45, 0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x53,
+  0x20, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x20, 0x28, 0x69, 0x64, 0x29,
+  0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4f, 0x4e, 0x20,
+  0x44, 0x45, 0x4c, 0x45, 0x54, 0x45, 0x20, 0x43, 0x41, 0x53, 0x43, 0x41,
+  0x44, 0x45, 0x2c, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x73, 0x63, 0x68, 0x65,
+  0x64, 0x75, 0x6c, 0x65, 0x5f, 0x69, 0x64, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x49, 0x4e, 0x54, 0x45, 0x47, 0x45, 0x52, 0x0a, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x44, 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x20,
+  0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x52, 0x45,
+  0x46, 0x45, 0x52, 0x45, 0x4e, 0x43, 0x45, 0x53, 0x20, 0x73, 0x63, 0x68,
+  0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x28, 0x69, 0x64, 0x29, 0x0a,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4f, 0x4e, 0x20, 0x44,
+  0x45, 0x4c, 0x45, 0x54, 0x45, 0x20, 0x53, 0x45, 0x54, 0x20, 0x44, 0x45,
+  0x46, 0x41, 0x55, 0x4c, 0x54, 0x0a, 0x29, 0x3b, 0x0a, 0x0a, 0x49, 0x4e,
+  0x53, 0x45, 0x52, 0x54, 0x20, 0x49, 0x4e, 0x54, 0x4f, 0x20, 0x73, 0x63,
+  0x68, 0x65, 0x64, 0x75, 0x6c, 0x65, 0x73, 0x20, 0x28, 0x75, 0x69, 0x64,
+  0x2c, 0x20, 0x6e, 0x61, 0x6d, 0x65, 0x2c, 0x20, 0x70, 0x65, 0x72, 0x69,
+  0x6f, 0x64, 0x73, 0x29, 0x20, 0x56, 0x41, 0x4c, 0x55, 0x45, 0x53, 0x20,
+  0x28, 0x78, 0x27, 0x36, 0x66, 0x36, 0x36, 0x36, 0x36, 0x30, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x27,
+  0x2c, 0x20, 0x27, 0x6f, 0x66, 0x66, 0x27, 0x2c, 0x20, 0x78, 0x27, 0x30,
+  0x30, 0x27, 0x29, 0x3b, 0x0a, 0x49, 0x4e, 0x53, 0x45, 0x52, 0x54, 0x20,
+  0x49, 0x4e, 0x54, 0x4f, 0x20, 0x73, 0x63, 0x68, 0x65, 0x64, 0x75, 0x6c,
+  0x65, 0x73, 0x20, 0x28, 0x75, 0x69, 0x64, 0x2c, 0x20, 0x6e, 0x61, 0x6d,
+  0x65, 0x2c, 0x20, 0x70, 0x65, 0x72, 0x69, 0x6f, 0x64, 0x73, 0x29, 0x20,
+  0x56, 0x41, 0x4c, 0x55, 0x45, 0x53, 0x20, 0x28, 0x78, 0x27, 0x36, 0x66,
+  0x36, 0x65, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
+  0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x27, 0x2c, 0x20, 0x20, 0x27, 0x6f,
+  0x6e, 0x27, 0x2c, 0x20, 0x78, 0x27, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
+  0x30, 0x30, 0x39, 0x46, 0x30, 0x35, 0x27, 0x29, 0x3b, 0x0a, 0x00
+};
+unsigned int sql_migration_0_sql_len = 1114;
diff --git a/sql/migration_0.sql b/sql/migration_0.sql
index e9dc18a..922c002 100644
--- a/sql/migration_0.sql
+++ b/sql/migration_0.sql
@@ -12,10 +12,8 @@ create table controllers
 
 create table relays
 (
-    id      INTEGER
-            PRIMARY KEY
-            AUTOINCREMENT,
     number  INTEGER
+            PRIMARY KEY
             NOT NULL,
     name    VARCHAR(128)
 );
diff --git a/src/handlers/command.c b/src/handlers/command.c
index d2c04c9..ae15e86 100644
--- a/src/handlers/command.c
+++ b/src/handlers/command.c
@@ -93,6 +93,7 @@ handler_command_relay_name_set(mpack_node_t map)
         return;
     }
     relay_set_name(global_controller->relays[relay_num], relay_name);
+    relay_debug(global_controller->relays[relay_num]);
     LOGGER_DEBUG("setting new name %s for relay %d\n", relay_name, relay_num);
     relay_save(global_controller->relays[relay_num]);
 }
@@ -113,25 +114,9 @@ handler_command_schedule_update(mpack_node_t map)
     if(schedule)
     {
         new_schedule->id = schedule->id;
-        schedule_free(schedule);
     }
-
     schedule_save(new_schedule);
-
-    int *relay_ids = junction_relay_schedule_get_relay_ids_with_schedule(new_schedule->id);
-
-    for(int i = 0; i < global_config.relay_count; ++i)
-    {
-        for(int j = 0; relay_ids[j] != 0; ++j)
-        {
-            if(global_controller->relays[i]->id == relay_ids[j])
-            {
-                relay_reload_schedules(global_controller->relays[i]);
-            }
-        }
-    }
-
-    free(relay_ids);
+    schedule_free(schedule);
     schedule_free(new_schedule);
 }
 
@@ -159,28 +144,18 @@ handler_command_relay_schedules_set(mpack_node_t map)
     {
         mpack_node_t schedule_map = mpack_node_array_at(schedules_array, i);
 
+        handler_command_schedule_update(schedule_map);
+
         uuid_t schedule_uid;
         memcpy(schedule_uid, mpack_node_data(mpack_node_map_uint(schedule_map, COMMAND_MAPPING_SCHEDULE_ID)), sizeof(uuid_t));
 
-        uint16_t periods_count = mpack_node_u16(mpack_node_map_uint(schedule_map, COMMAND_MAPPING_PERIODS_COUNT));
-        uint16_t *periods = (uint16_t*)mpack_node_bin_data(mpack_node_map_uint(schedule_map, COMMAND_MAPPING_PERIODS_BLOB));
-
         schedule_t *schedule = schedule_get_by_uid(schedule_uid);
 
-        schedule_t *new_schedule = schedule_create(schedule_uid, periods_count, periods);
-
-        if(schedule)
-        {
-            new_schedule->id = schedule->id;
-            schedule_free(schedule);
-        }
-
-        schedule_save(new_schedule);
-
-        junction_relay_schedule_insert(i, target_relay->id, new_schedule->id);
+        junction_relay_schedule_insert(i, target_relay->id, schedule->id);
     }
 
     relay_reload_schedules(target_relay);
+    relay_debug(target_relay);
 
     database_transaction_commit();
 }
@@ -207,7 +182,7 @@ handler_command(struct mg_connection *c, int ev, void *ev_data)
     mpack_tree_parse(&tree);
     mpack_node_t root = mpack_tree_root(&tree);
 
-    uint16_t command_code = mpack_node_u16(mpack_node_map_uint(root, COMMAND_MAPPING_CODE));
+    uint16_t command_code = mpack_node_u8(mpack_node_map_uint(root, COMMAND_MAPPING_CODE));
 
     LOGGER_DEBUG("received command %d\n", command_code);
 
@@ -246,6 +221,4 @@ handler_command(struct mg_connection *c, int ev, void *ev_data)
     {
         LOGGER_WARNING("error when destroying mpack tree\n");
     }
-    LOGGER_DEBUG("done with command %d - closing connection\n", command_code);
-    c->flags |= MG_F_SEND_AND_CLOSE;
 }
diff --git a/src/handlers/loop.c b/src/handlers/loop.c
index 2076952..76a5999 100644
--- a/src/handlers/loop.c
+++ b/src/handlers/loop.c
@@ -34,25 +34,21 @@ handler_loop(struct mg_connection *c_mqtt)
         int is_on = 0;
         
         int is_on_schedule = relay_is_on_schedule(relay, &time_now);
-        int pulse_relay = global_config.relay_configs[i].pulse_duration;
 
-        if(is_on_schedule)
+        if(relay->is_on_schedule != is_on_schedule && relay->is_on_schedule != -1)
         {
-            if(!pulse_relay)
-            {
-                is_on = 1;
-                LOGGER_DEBUG("relay %d is active\n", i);
-            }
-            if(pulse_relay && relay->pulse_timer)
-            {
-                is_on = 1;
-                --relay->pulse_timer;
-                LOGGER_DEBUG("relay %d is pulsing for %d more seconds\n", i, relay->pulse_timer);
-            }
+            relay->pulse_timer = global_config.relay_configs[i].pulse_duration;
         }
-        else
+        if(is_on_schedule && !global_config.relay_configs[i].pulse_duration)
         {
-            relay->pulse_timer = 0;
+            is_on = 1;
+            LOGGER_DEBUG("relay %d is active\n", i);
+        }
+        if(relay->pulse_timer > 0)
+        {
+            is_on = 1;
+            --relay->pulse_timer;
+            LOGGER_DEBUG("relay %d is pulsing for %d more seconds\n", i, relay->pulse_timer);
         }
 
         if(relay->is_on != is_on)
@@ -64,14 +60,11 @@ handler_loop(struct mg_connection *c_mqtt)
             sprintf(topic_buf, "controller/%s/relay/%u", controller_uid, i);
             sprintf(payload_buf, "%u", is_on);
             mg_mqtt_publish(c_mqtt, topic_buf, 0, MG_MQTT_QOS(0), payload_buf, strlen(payload_buf));
-            relay->sent_to_broker = (rand() % 45) + 15;
+            relay->sent_to_broker = 1;
             LOGGER_DEBUG("sent relay %d status (%d) to mqtt broker\n", i, is_on);
         }
-        if(relay->sent_to_broker)
-        {
-            --relay->sent_to_broker;
-        }
         relay->is_on = is_on;
+        relay->is_on_schedule = is_on_schedule;
 
         if(global_config.relay_configs[i].inverted)
         {
diff --git a/src/main.c b/src/main.c
index a13c75e..cd998b6 100644
--- a/src/main.c
+++ b/src/main.c
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <stdio.h>
 #include <time.h>
+#include <lmdb.h>
 #include <signal.h>
 #include <syslog.h>
 
@@ -121,6 +122,7 @@ main(int argc, const char** argv)
     if(!global_controller)
     {
         global_controller = controller_create();
+
         controller_save();
     }
 
@@ -128,13 +130,9 @@ main(int argc, const char** argv)
     connection_mqtt_connect(&mgr);
     struct mg_connection *c_command = connection_command_bind(&mgr);
 
-    if(global_controller->command_port == 0)
-    {
-        global_controller->command_port = helper_get_port(c_command->sock);
-        controller_save();
-    }
+    global_controller->command_port = helper_get_port(c_command->sock);
 
-    controller_debug(global_controller);
+    controller_save();
 
     helper_drop_privileges();
 
diff --git a/src/models/controller.c b/src/models/controller.c
index 729404b..58c1554 100644
--- a/src/models/controller.c
+++ b/src/models/controller.c
@@ -60,11 +60,10 @@ controller_db_select_mapper(sqlite3_stmt *stmt)
     uint8_t i;
     for(i = 0; i < global_config.relay_count; ++i)
     {
-        new_controller->relays[i] = relay_load(i);
+        new_controller->relays[i] = relay_load(new_controller->id);
         if(!new_controller->relays[i])
         {
             new_controller->relays[i] = relay_create(i);
-            relay_save(new_controller->relays[i]);
         }
     }
     return new_controller;
@@ -207,11 +206,10 @@ controller_create(void)
     uint8_t i;
     for(i = 0; i < global_config.relay_count; ++i)
     {
-        new_controller->relays[i] = relay_load(i);
+        new_controller->relays[i] = relay_load(new_controller->id);
         if(!new_controller->relays[i])
         {
             new_controller->relays[i] = relay_create(i);
-            relay_save(new_controller->relays[i]);
         }
     }
 
diff --git a/src/models/junction_relay_schedule.c b/src/models/junction_relay_schedule.c
index 8d623c0..fca0ffd 100644
--- a/src/models/junction_relay_schedule.c
+++ b/src/models/junction_relay_schedule.c
@@ -23,7 +23,7 @@ junction_relay_schedule_insert(uint8_t weekday, int relay_id, int schedule_id)
     rc = sqlite3_step(stmt);
     if (rc != SQLITE_DONE)
     {
-        LOGGER_ERR("error inserting data: %s\n", sqlite3_errmsg(global_database));
+        LOGGER_ERR("error inserting data: %s", sqlite3_errmsg(global_database));
         return false;
     }
 
@@ -88,15 +88,3 @@ junction_relay_schedule_remove_for_relay(int relay_id)
 
     return rc == SQLITE_DONE;
 }
-
-
-int*
-junction_relay_schedule_get_relay_ids_with_schedule(int schedule_id)
-{
-    sqlite3_stmt *stmt;
-
-    sqlite3_prepare_v2(global_database, "SELECT DISTINCT relay_id FROM junction_relay_schedule WHERE schedule_id=?1;", -1, &stmt, NULL);
-    sqlite3_bind_int(stmt, 1, schedule_id);
-
-    return database_helper_get_ids(stmt);
-}
diff --git a/src/models/relay.c b/src/models/relay.c
index 38c3aa0..317f575 100644
--- a/src/models/relay.c
+++ b/src/models/relay.c
@@ -55,13 +55,20 @@ relay_db_select_mapper(sqlite3_stmt *stmt)
                 break;
         }
     }
-    
-    memset(new_relay->schedules, 0, sizeof(schedule_t*) * 7);
-    relay_reload_schedules(new_relay);
 
-    new_relay->is_on = -1;
-    new_relay->pulse_timer = 0;
-    new_relay->sent_to_broker = 0;
+    schedule_t **schedules = schedule_get_relay_weekdays(new_relay->id);
+    for(int i = 0; i < 7; ++i)
+    {
+        if(schedules[i] == NULL)
+        {
+            LOGGER_ERR("got only %d/7 schedules for relay_id %d\n", i, new_relay->id);
+            relay_free(new_relay);
+            free(schedules);
+            return NULL;
+        }
+        new_relay->schedules[i] = schedules[i];
+    }
+    free(schedules); // don't free list, because contents are kept in relay->schedules
 
     return new_relay;
 }
@@ -112,11 +119,11 @@ relay_save(relay_t *relay)
     sqlite3_stmt *stmt;
     if(relay->id)
     {
-        sqlite3_prepare_v2(global_database, "UPDATE relays set number = ?2, name = ?3 WHERE id = ?1;", -1, &stmt, NULL);
+        sqlite3_prepare_v2(global_database, "UPDATE relays set number = ?2, name = ?3, controller_id = ?4 WHERE id = ?1;", -1, &stmt, NULL);
     }
     else
     {
-        sqlite3_prepare_v2(global_database, "INSERT INTO relays(number, name) values (?2, ?3);", -1, &stmt, NULL);
+        sqlite3_prepare_v2(global_database, "INSERT INTO relays(number, name, controller_id) values (?2, ?3, ?4);", -1, &stmt, NULL);
     }
 
     int result = db_update_insert(relay, stmt);
@@ -142,7 +149,6 @@ relay_save(relay_t *relay)
         if(relay->id == 0)
         {
             relay->id = sqlite3_last_insert_rowid(global_database);
-            LOGGER_DEBUG("new relay - new id: %d\n", relay->id);
         }
 
         LOGGER_DEBUG("cleaning relay_schedule junction\n");
@@ -171,11 +177,11 @@ relay_create(uint8_t number)
 {
     relay_t *new_relay = malloc(sizeof(relay_t));
 
-    new_relay->id = 0;
     new_relay->number = number;
     new_relay->name[0] = '\0';
 
     new_relay->is_on = -1;
+    new_relay->is_on_schedule = -1;
     new_relay->pulse_timer = 0;
     new_relay->sent_to_broker = 0;
 
@@ -211,31 +217,23 @@ void
 relay_reload_schedules(relay_t *relay)
 {
     schedule_t **schedules = schedule_get_relay_weekdays(relay->id);
-
-    uuid_t off_id;
-    memset(off_id, 0, sizeof(uuid_t));
-    memcpy(off_id, "off", 3);
-
-    int fill_with_off = 0;
     for(int i = 0; i < 7; ++i)
     {
-        if(schedules[i] == NULL || fill_with_off)
+        if(schedules[i] == NULL)
         {
-            LOGGER_WARNING("got only %d/7 schedules for relay_id %d\n", i, relay->id);
-            relay->schedules[i] = schedule_get_by_uid(off_id);
-
-            fill_with_off = 1;
-        }
-        else
-        {
-            if(relay->schedules[i])
-            {
-                schedule_free(relay->schedules[i]);
-            }
-            relay->schedules[i] = schedules[i];
+            LOGGER_ERR("got only %d/7 schedules for relay_id %d\n", i, relay->id);
+            relay_free(relay);
+            schedule_free_list(schedules);
+            return;
         }
     }
 
+
+    for(int i = 0; i < 7; ++i)
+    {
+        schedule_free(relay->schedules[i]);
+        relay->schedules[i] = schedules[i];
+    }
     free(schedules); // don't free list, because contents are kept in relay->schedules
 }
 
@@ -250,12 +248,12 @@ int
 relay_is_on_schedule(relay_t *relay, struct tm *time_struct)
 {
     schedule_t *schedule = relay->schedules[helper_get_weekday(time_struct)];
-    if(schedule->periods_count == 0)
+    if(schedule->length == 0)
     {
         return 0;
     }
 
-    for(uint16_t i = 0; i < schedule->periods_count; ++i)
+    for(uint16_t i = 0; i < schedule->length; ++i)
     {
         if(period_includes_time(schedule->periods[i], time_struct))
         {
@@ -273,8 +271,8 @@ relay_debug(relay_t *relay)
         LOGGER_DEBUG("relay is NULL\n");
         return;
     }
-    LOGGER_DEBUG("(1/3) %3d @ %p\n", relay->number, (void*)relay);
-    LOGGER_DEBUG("(2/3) id: %3d; name: %s\n", relay->id, relay->name);
+    LOGGER_DEBUG("(1/3) %d @ %p\n", relay->number, (void*)relay);
+    LOGGER_DEBUG("(2/3) name: %s\n", relay->name);
     LOGGER_DEBUG("(3/3) schedules @ %p:\n", (void*)relay->schedules);
     for(int i = 0; i < 7; ++i)
     {
diff --git a/src/models/schedule.c b/src/models/schedule.c
index 4c279c9..188358e 100644
--- a/src/models/schedule.c
+++ b/src/models/schedule.c
@@ -44,7 +44,6 @@ schedule_db_select_mapper(sqlite3_stmt *stmt)
                 break;
             case 'p': // periods
                 periods_blob = sqlite3_column_blob(stmt, i);
-                new_schedule->periods_count = periods_blob[0];
                 new_schedule->periods = malloc(sizeof(period_t) * periods_blob[0]);
 
                 for(int i = 0; i < periods_blob[0]; ++i)
@@ -187,10 +186,9 @@ schedule_create(uuid_t uid, uint16_t length, uint16_t *periods_blob)
 {
     schedule_t *new_schedule = malloc(sizeof(schedule_t));
 
-    new_schedule->id = 0;
     memmove(new_schedule->uid, uid, sizeof(uuid_t));
 
-    new_schedule->periods_count = length;
+    new_schedule->length = length;
     new_schedule->periods = NULL;
 
     if(length)
@@ -210,10 +208,10 @@ schedule_create(uuid_t uid, uint16_t length, uint16_t *periods_blob)
 uint16_t*
 schedule_periods_to_blob(schedule_t *schedule)
 {
-    uint16_t *periods_blob = malloc(sizeof(uint16_t) * ((2 * schedule->periods_count) + 1));
-    periods_blob[0] = schedule->periods_count;
+    uint16_t *periods_blob = malloc(sizeof(uint16_t) * ((2 * schedule->length) + 1));
+    periods_blob[0] = schedule->length;
 
-    for(uint16_t i = 0; i < schedule->periods_count; ++i)
+    for(uint16_t i = 0; i < schedule->length; ++i)
     {
 
         periods_blob[1 + (i * 2)] = schedule->periods[i].start;
@@ -296,15 +294,16 @@ schedule_debug(schedule_t *schedule)
         return;
     }
     char uuid_str[UUID_STR_LEN];
-    schedule_uid_unparse(schedule->uid, uuid_str);
+    uuid_unparse(schedule->uid, uuid_str);
     LOGGER_DEBUG("(1/3) %s @ %p\n", uuid_str, (void*)schedule);
-    LOGGER_DEBUG("(2/3) id: %3d; period count: %3d\n", schedule->id, schedule->periods_count);
+    LOGGER_DEBUG("(2/4) period count: %3d\n", schedule->length);
+    LOGGER_DEBUG("(3/4) weekday: %3d\n", schedule->weekday);
 
     // one block: "HH:MM-HH:MM, " --> size: 13 (14 with '\0')
-    char *periods_debug_str = malloc(sizeof(char) * ((schedule->periods_count * 13) + 1));
+    char *periods_debug_str = malloc(sizeof(char) * ((schedule->length * 13) + 1));
     periods_debug_str[0] = '\0';
 
-    for(uint16_t i = 0; i < schedule->periods_count; ++i)
+    for(uint16_t i = 0; i < schedule->length; ++i)
     {
         sprintf(
             periods_debug_str + (13 * i),
@@ -316,7 +315,7 @@ schedule_debug(schedule_t *schedule)
         );
     }
 
-    LOGGER_DEBUG("(3/3) periods: %s\n", periods_debug_str);
+    LOGGER_DEBUG("(4/4) periods: %s\n", periods_debug_str);
 
     free(periods_debug_str);
 }