diff --git a/src/knot/nameserver/ixfr.c b/src/knot/nameserver/ixfr.c
index 77e85d9d0035e19e89b6861dafa74cb0e7dea8a2..825f59b5b6a553119874c911074eeec7d3c7b7bd 100644
--- a/src/knot/nameserver/ixfr.c
+++ b/src/knot/nameserver/ixfr.c
@@ -162,7 +162,7 @@ static int ixfr_process_changeset(knot_pkt_t *pkt, const void *item,
 #undef IXFR_SAFE_PUT
 
 /*! \brief Loads IXFRs from journal. */
-static int ixfr_load_chsets(list_t *chgsets, const zone_t *zone,
+static int ixfr_load_chsets(list_t *chgsets, zone_t *zone,
                             const knot_rrset_t *their_soa)
 {
 	assert(chgsets);
@@ -176,7 +176,10 @@ static int ixfr_load_chsets(list_t *chgsets, const zone_t *zone,
 		return KNOT_EUPTODATE;
 	}
 
+	pthread_mutex_lock(&zone->journal_lock);
 	ret = journal_load_changesets(zone, chgsets, serial_from, serial_to);
+	pthread_mutex_unlock(&zone->journal_lock);
+
 	if (ret != KNOT_EOK) {
 		changesets_free(chgsets);
 	}
@@ -241,7 +244,7 @@ static int ixfr_answer_init(struct query_data *qdata)
 	const knot_rrset_t *their_soa = &knot_pkt_section(qdata->query, KNOT_AUTHORITY)->rr[0];
 	list_t chgsets;
 	init_list(&chgsets);
-	int ret = ixfr_load_chsets(&chgsets, qdata->zone, their_soa);
+	int ret = ixfr_load_chsets(&chgsets, (zone_t *)qdata->zone, their_soa);
 	if (ret != KNOT_EOK) {
 		dbg_ns("%s: failed to load changesets => %d\n", __func__, ret);
 		return ret;
diff --git a/src/knot/zone/zone-load.c b/src/knot/zone/zone-load.c
index 777737d77e0386508a891b57ee5e14137595bd1a..d643596e608ebe76f4d3f5d55bfb9621b99e3dc4 100644
--- a/src/knot/zone/zone-load.c
+++ b/src/knot/zone/zone-load.c
@@ -97,7 +97,11 @@ int zone_load_journal(zone_t *zone, zone_contents_t *contents)
 	/*! \todo Check what should be the upper bound. */
 	list_t chgs;
 	init_list(&chgs);
+
+	pthread_mutex_lock(&zone->journal_lock);
 	int ret = journal_load_changesets(zone, &chgs, serial, serial - 1);
+	pthread_mutex_unlock(&zone->journal_lock);
+
 	if ((ret != KNOT_EOK && ret != KNOT_ERANGE) || EMPTY_LIST(chgs)) {
 		changesets_free(&chgs);
 		/* Absence of records is not an error. */
diff --git a/src/knot/zone/zone.c b/src/knot/zone/zone.c
index 8d7f5d496bca8d2d04b38f7821eb0c79071d826d..7584a0801c602567d31ac0ae993cee8aae775fd8 100644
--- a/src/knot/zone/zone.c
+++ b/src/knot/zone/zone.c
@@ -75,6 +75,9 @@ zone_t* zone_new(conf_zone_t *conf)
 	zone->ddns_queue_size = 0;
 	init_list(&zone->ddns_queue);
 
+	// Journal lock
+	pthread_mutex_init(&zone->journal_lock, NULL);
+
 	// Initialize events
 	zone_events_init(zone);
 
@@ -95,6 +98,7 @@ void zone_free(zone_t **zone_ptr)
 
 	free_ddns_queue(zone);
 	pthread_mutex_destroy(&zone->ddns_lock);
+	pthread_mutex_destroy(&zone->journal_lock);
 
 	/* Free assigned config. */
 	conf_free_zone(zone->conf);
@@ -113,18 +117,18 @@ int zone_change_store(zone_t *zone, changeset_t *change)
 
 	conf_zone_t *conf = zone->conf;
 
+	pthread_mutex_lock(&zone->journal_lock);
 	int ret = journal_store_changeset(change, conf->ixfr_db, conf->ixfr_fslimit);
 	if (ret == KNOT_EBUSY) {
 		log_zone_notice(zone->name, "journal is full, flushing");
 
 		/* Transaction rolled back, journal released, we may flush. */
 		ret = zone_flush_journal(zone);
-		if (ret != KNOT_EOK) {
-			return ret;
+		if (ret == KNOT_EOK) {
+			ret = journal_store_changeset(change, conf->ixfr_db, conf->ixfr_fslimit);
 		}
-
-		return journal_store_changeset(change, conf->ixfr_db, conf->ixfr_fslimit);
 	}
+	pthread_mutex_unlock(&zone->journal_lock);
 
 	return ret;
 }
@@ -136,18 +140,19 @@ int zone_changes_store(zone_t *zone, list_t *chgs)
 
 	conf_zone_t *conf = zone->conf;
 
+	pthread_mutex_lock(&zone->journal_lock);
 	int ret = journal_store_changesets(chgs, conf->ixfr_db, conf->ixfr_fslimit);
+
 	if (ret == KNOT_EBUSY) {
 		log_zone_notice(zone->name, "journal is full, flushing");
 
 		/* Transaction rolled back, journal released, we may flush. */
 		ret = zone_flush_journal(zone);
-		if (ret != KNOT_EOK) {
-			return ret;
+		if (ret == KNOT_EOK) {
+			ret = journal_store_changesets(chgs, conf->ixfr_db, conf->ixfr_fslimit);
 		}
-
-		return journal_store_changesets(chgs, conf->ixfr_db, conf->ixfr_fslimit);
 	}
+	pthread_mutex_unlock(&zone->journal_lock);
 
 	return ret;
 }
diff --git a/src/knot/zone/zone.h b/src/knot/zone/zone.h
index 0fc39821a8e0b5e5827d4a0a15f09f18c155c6e7..2d8c2fc1f35dc1775761b0b8b11d5995b2e39d5a 100644
--- a/src/knot/zone/zone.h
+++ b/src/knot/zone/zone.h
@@ -61,6 +61,9 @@ typedef struct zone
 	pthread_mutex_t ddns_lock;
 	size_t ddns_queue_size;
 	list_t ddns_queue;
+	
+	/*! \brief Journal access lock. */
+	pthread_mutex_t journal_lock;
 
 	/*! \brief Zone events. */
 	zone_events_t events;     /*!< Zone events timers. */