diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index 8a6a9d10..a2633ad8 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -257,12 +257,12 @@
     "query_log_cleared": "The query log has been successfully cleared",
     "query_log_updated": "The query log has been successfully updated",
     "query_log_clear": "Clear query logs",
-    "query_log_retention": "Query logs retention",
+    "query_log_retention": "Query logs rotation",
     "query_log_enable": "Enable log",
     "query_log_configuration": "Logs configuration",
     "query_log_disabled": "The query log is disabled and can be configured in the <0>settings</0>",
     "query_log_strict_search": "Use double quotes for strict search",
-    "query_log_retention_confirm": "Are you sure you want to change query log retention? If you decrease the interval value, some data will be lost",
+    "query_log_retention_confirm": "Are you sure you want to change query log rotation? If you decrease the interval value, some data will be lost",
     "anonymize_client_ip": "Anonymize client IP",
     "anonymize_client_ip_desc": "Don't save the client's full IP address to logs or statistics",
     "dns_config": "DNS server configuration",
@@ -669,6 +669,8 @@
     "disable_notify_for_hours_plural": "Disable protection for {{count}} hours",
     "disable_notify_until_tomorrow": "Disable protection until tomorrow",
     "enable_protection_timer": "Protection will be enabled in {{time}}",
+    "custom_retention_input": "Enter retention in hours",
+    "custom_rotation_input": "Enter rotation in hours",
     "protection_section_label": "Protection",
     "log_and_stats_section_label": "Query log and statistics",
     "ignore_query_log": "Ignore this client in query log",
diff --git a/client/src/components/Settings/LogsConfig/Form.js b/client/src/components/Settings/LogsConfig/Form.js
index b29b974e..dbecc183 100644
--- a/client/src/components/Settings/LogsConfig/Form.js
+++ b/client/src/components/Settings/LogsConfig/Form.js
@@ -1,25 +1,37 @@
-import React from 'react';
+import React, { useEffect } from 'react';
 import PropTypes from 'prop-types';
-import { Field, reduxForm } from 'redux-form';
+import {
+    change,
+    Field,
+    formValueSelector,
+    reduxForm,
+} from 'redux-form';
+import { connect } from 'react-redux';
 import { Trans, withTranslation } from 'react-i18next';
 import flow from 'lodash/flow';
 
 import {
     CheckboxField,
-    renderRadioField,
     toFloatNumber,
-    renderTextareaField,
+    renderTextareaField, renderInputField, renderRadioField,
 } from '../../../helpers/form';
 import {
     FORM_NAME,
     QUERY_LOG_INTERVALS_DAYS,
     HOUR,
     DAY,
+    RETENTION_CUSTOM,
+    RETENTION_CUSTOM_INPUT,
+    RETENTION_RANGE,
+    CUSTOM_INTERVAL,
 } from '../../../helpers/constants';
 import '../FormButton.css';
 
+
 const getIntervalTitle = (interval, t) => {
     switch (interval) {
+        case RETENTION_CUSTOM:
+            return t('settings_custom');
         case 6 * HOUR:
             return t('interval_6_hour');
         case DAY:
@@ -42,11 +54,26 @@ const getIntervalFields = (processing, t, toNumber) => QUERY_LOG_INTERVALS_DAYS.
     />
 ));
 
-const Form = (props) => {
+let Form = (props) => {
     const {
-        handleSubmit, submitting, invalid, processing, processingClear, handleClear, t,
+        handleSubmit,
+        submitting,
+        invalid,
+        processing,
+        processingClear,
+        handleClear,
+        t,
+        interval,
+        customInterval,
+        dispatch,
     } = props;
 
+    useEffect(() => {
+        if (QUERY_LOG_INTERVALS_DAYS.includes(interval)) {
+            dispatch(change(FORM_NAME.LOG_CONFIG, CUSTOM_INTERVAL, null));
+        }
+    }, [interval]);
+
     return (
         <form onSubmit={handleSubmit}>
             <div className="form__group form__group--settings">
@@ -73,6 +100,37 @@ const Form = (props) => {
             </label>
             <div className="form__group form__group--settings">
                 <div className="custom-controls-stacked">
+                    <Field
+                        key={RETENTION_CUSTOM}
+                        name="interval"
+                        type="radio"
+                        component={renderRadioField}
+                        value={QUERY_LOG_INTERVALS_DAYS.includes(interval)
+                            ? RETENTION_CUSTOM
+                            : interval
+                        }
+                        placeholder={getIntervalTitle(RETENTION_CUSTOM, t)}
+                        normalize={toFloatNumber}
+                        disabled={processing}
+                    />
+                    {!QUERY_LOG_INTERVALS_DAYS.includes(interval) && (
+                        <div className="form__group--input">
+                            <div className="form__desc form__desc--top">
+                                {t('custom_rotation_input')}
+                            </div>
+                            <Field
+                                key={RETENTION_CUSTOM_INPUT}
+                                name={CUSTOM_INTERVAL}
+                                type="number"
+                                className="form-control"
+                                component={renderInputField}
+                                disabled={processing}
+                                normalize={toFloatNumber}
+                                min={RETENTION_RANGE.MIN}
+                                max={RETENTION_RANGE.MAX}
+                            />
+                        </div>
+                    )}
                     {getIntervalFields(processing, t, toFloatNumber)}
                 </div>
             </div>
@@ -96,7 +154,12 @@ const Form = (props) => {
                 <button
                     type="submit"
                     className="btn btn-success btn-standard btn-large"
-                    disabled={submitting || invalid || processing}
+                    disabled={
+                        submitting
+                        || invalid
+                        || processing
+                        || (!QUERY_LOG_INTERVALS_DAYS.includes(interval) && !customInterval)
+                    }
                 >
                     <Trans>save_btn</Trans>
                 </button>
@@ -121,8 +184,22 @@ Form.propTypes = {
     processing: PropTypes.bool.isRequired,
     processingClear: PropTypes.bool.isRequired,
     t: PropTypes.func.isRequired,
+    interval: PropTypes.number,
+    customInterval: PropTypes.number,
+    dispatch: PropTypes.func.isRequired,
 };
 
+const selector = formValueSelector(FORM_NAME.LOG_CONFIG);
+
+Form = connect((state) => {
+    const interval = selector(state, 'interval');
+    const customInterval = selector(state, CUSTOM_INTERVAL);
+    return {
+        interval,
+        customInterval,
+    };
+})(Form);
+
 export default flow([
     withTranslation(),
     reduxForm({ form: FORM_NAME.LOG_CONFIG }),
diff --git a/client/src/components/Settings/LogsConfig/index.js b/client/src/components/Settings/LogsConfig/index.js
index 146a77b0..3e609a2d 100644
--- a/client/src/components/Settings/LogsConfig/index.js
+++ b/client/src/components/Settings/LogsConfig/index.js
@@ -4,15 +4,22 @@ import { withTranslation } from 'react-i18next';
 
 import Card from '../../ui/Card';
 import Form from './Form';
+import { HOUR } from '../../../helpers/constants';
 
 class LogsConfig extends Component {
     handleFormSubmit = (values) => {
         const { t, interval: prevInterval } = this.props;
-        const { interval } = values;
+        const { interval, customInterval, ...rest } = values;
 
-        const data = { ...values, ignored: values.ignored ? values.ignored.split('\n') : [] };
+        const newInterval = customInterval ? customInterval * HOUR : interval;
 
-        if (interval !== prevInterval) {
+        const data = {
+            ...rest,
+            ignored: values.ignored ? values.ignored.split('\n') : [],
+            interval: newInterval,
+        };
+
+        if (newInterval < prevInterval) {
             // eslint-disable-next-line no-alert
             if (window.confirm(t('query_log_retention_confirm'))) {
                 this.props.setLogsConfig(data);
@@ -32,7 +39,14 @@ class LogsConfig extends Component {
 
     render() {
         const {
-            t, enabled, interval, processing, processingClear, anonymize_client_ip, ignored,
+            t,
+            enabled,
+            interval,
+            processing,
+            processingClear,
+            anonymize_client_ip,
+            ignored,
+            customInterval,
         } = this.props;
 
         return (
@@ -46,6 +60,7 @@ class LogsConfig extends Component {
                         initialValues={{
                             enabled,
                             interval,
+                            customInterval,
                             anonymize_client_ip,
                             ignored: ignored.join('\n'),
                         }}
@@ -62,6 +77,7 @@ class LogsConfig extends Component {
 
 LogsConfig.propTypes = {
     interval: PropTypes.number.isRequired,
+    customInterval: PropTypes.number,
     enabled: PropTypes.bool.isRequired,
     anonymize_client_ip: PropTypes.bool.isRequired,
     processing: PropTypes.bool.isRequired,
diff --git a/client/src/components/Settings/Settings.css b/client/src/components/Settings/Settings.css
index b6903427..25532b45 100644
--- a/client/src/components/Settings/Settings.css
+++ b/client/src/components/Settings/Settings.css
@@ -18,6 +18,11 @@
     font-size: 14px;
 }
 
+.form__group--input {
+    max-width: 300px;
+    margin: 0 1.5rem 10px;
+}
+
 .form__group--checkbox {
     margin-bottom: 25px;
 }
diff --git a/client/src/components/Settings/StatsConfig/Form.js b/client/src/components/Settings/StatsConfig/Form.js
index e9cd02fd..087e9578 100644
--- a/client/src/components/Settings/StatsConfig/Form.js
+++ b/client/src/components/Settings/StatsConfig/Form.js
@@ -1,32 +1,44 @@
-import React from 'react';
+import React, { useEffect } from 'react';
 import PropTypes from 'prop-types';
-import { Field, reduxForm } from 'redux-form';
+import {
+    change, Field, formValueSelector, reduxForm,
+} from 'redux-form';
 import { Trans, withTranslation } from 'react-i18next';
 import flow from 'lodash/flow';
+import { connect } from 'react-redux';
+
 
 import {
     renderRadioField,
     toNumber,
     CheckboxField,
     renderTextareaField,
+    toFloatNumber,
+    renderInputField,
 } from '../../../helpers/form';
 import {
     FORM_NAME,
     STATS_INTERVALS_DAYS,
     DAY,
+    RETENTION_CUSTOM,
+    RETENTION_CUSTOM_INPUT,
+    CUSTOM_INTERVAL,
+    RETENTION_RANGE,
 } from '../../../helpers/constants';
 import '../FormButton.css';
 
 const getIntervalTitle = (intervalMs, t) => {
-    switch (intervalMs / DAY) {
-        case 1:
+    switch (intervalMs) {
+        case RETENTION_CUSTOM:
+            return t('settings_custom');
+        case DAY:
             return t('interval_24_hour');
         default:
             return t('interval_days', { count: intervalMs / DAY });
     }
 };
 
-const Form = (props) => {
+let Form = (props) => {
     const {
         handleSubmit,
         processing,
@@ -35,8 +47,17 @@ const Form = (props) => {
         handleReset,
         processingReset,
         t,
+        interval,
+        customInterval,
+        dispatch,
     } = props;
 
+    useEffect(() => {
+        if (STATS_INTERVALS_DAYS.includes(interval)) {
+            dispatch(change(FORM_NAME.STATS_CONFIG, CUSTOM_INTERVAL, null));
+        }
+    }, [interval]);
+
     return (
         <form onSubmit={handleSubmit}>
             <div className="form__group form__group--settings">
@@ -56,6 +77,37 @@ const Form = (props) => {
             </div>
             <div className="form__group form__group--settings mt-2">
                 <div className="custom-controls-stacked">
+                    <Field
+                        key={RETENTION_CUSTOM}
+                        name="interval"
+                        type="radio"
+                        component={renderRadioField}
+                        value={STATS_INTERVALS_DAYS.includes(interval)
+                            ? RETENTION_CUSTOM
+                            : interval
+                        }
+                        placeholder={getIntervalTitle(RETENTION_CUSTOM, t)}
+                        normalize={toFloatNumber}
+                        disabled={processing}
+                    />
+                    {!STATS_INTERVALS_DAYS.includes(interval) && (
+                        <div className="form__group--input">
+                            <div className="form__desc form__desc--top">
+                                {t('custom_retention_input')}
+                            </div>
+                            <Field
+                                key={RETENTION_CUSTOM_INPUT}
+                                name={CUSTOM_INTERVAL}
+                                type="number"
+                                className="form-control"
+                                component={renderInputField}
+                                disabled={processing}
+                                normalize={toFloatNumber}
+                                min={RETENTION_RANGE.MIN}
+                                max={RETENTION_RANGE.MAX}
+                            />
+                        </div>
+                    )}
                     {STATS_INTERVALS_DAYS.map((interval) => (
                         <Field
                             key={interval}
@@ -90,7 +142,12 @@ const Form = (props) => {
                 <button
                     type="submit"
                     className="btn btn-success btn-standard btn-large"
-                    disabled={submitting || invalid || processing}
+                    disabled={
+                        submitting
+                        || invalid
+                        || processing
+                        || (!STATS_INTERVALS_DAYS.includes(interval) && !customInterval)
+                    }
                 >
                     <Trans>save_btn</Trans>
                 </button>
@@ -116,8 +173,22 @@ Form.propTypes = {
     processing: PropTypes.bool.isRequired,
     processingReset: PropTypes.bool.isRequired,
     t: PropTypes.func.isRequired,
+    interval: PropTypes.number,
+    customInterval: PropTypes.number,
+    dispatch: PropTypes.func.isRequired,
 };
 
+const selector = formValueSelector(FORM_NAME.STATS_CONFIG);
+
+Form = connect((state) => {
+    const interval = selector(state, 'interval');
+    const customInterval = selector(state, CUSTOM_INTERVAL);
+    return {
+        interval,
+        customInterval,
+    };
+})(Form);
+
 export default flow([
     withTranslation(),
     reduxForm({ form: FORM_NAME.STATS_CONFIG }),
diff --git a/client/src/components/Settings/StatsConfig/index.js b/client/src/components/Settings/StatsConfig/index.js
index 83807afa..7b68064c 100644
--- a/client/src/components/Settings/StatsConfig/index.js
+++ b/client/src/components/Settings/StatsConfig/index.js
@@ -4,13 +4,18 @@ import { withTranslation } from 'react-i18next';
 
 import Card from '../../ui/Card';
 import Form from './Form';
+import { HOUR } from '../../../helpers/constants';
 
 class StatsConfig extends Component {
-    handleFormSubmit = ({ enabled, interval, ignored }) => {
+    handleFormSubmit = ({
+        enabled, interval, ignored, customInterval,
+    }) => {
         const { t, interval: prevInterval } = this.props;
+        const newInterval = customInterval ? customInterval * HOUR : interval;
+
         const config = {
             enabled,
-            interval,
+            interval: newInterval,
             ignored: ignored ? ignored.split('\n') : [],
         };
 
@@ -33,7 +38,13 @@ class StatsConfig extends Component {
 
     render() {
         const {
-            t, interval, processing, processingReset, ignored, enabled,
+            t,
+            interval,
+            customInterval,
+            processing,
+            processingReset,
+            ignored,
+            enabled,
         } = this.props;
 
         return (
@@ -46,6 +57,7 @@ class StatsConfig extends Component {
                     <Form
                         initialValues={{
                             interval,
+                            customInterval,
                             enabled,
                             ignored: ignored.join('\n'),
                         }}
@@ -62,6 +74,7 @@ class StatsConfig extends Component {
 
 StatsConfig.propTypes = {
     interval: PropTypes.number.isRequired,
+    customInterval: PropTypes.number,
     ignored: PropTypes.array.isRequired,
     enabled: PropTypes.bool.isRequired,
     processing: PropTypes.bool.isRequired,
diff --git a/client/src/components/Settings/index.js b/client/src/components/Settings/index.js
index 43aff62e..8ef96bd8 100644
--- a/client/src/components/Settings/index.js
+++ b/client/src/components/Settings/index.js
@@ -124,6 +124,7 @@ class Settings extends Component {
                                     enabled={queryLogs.enabled}
                                     ignored={queryLogs.ignored}
                                     interval={queryLogs.interval}
+                                    customInterval={queryLogs.customInterval}
                                     anonymize_client_ip={queryLogs.anonymize_client_ip}
                                     processing={queryLogs.processingSetConfig}
                                     processingClear={queryLogs.processingClear}
@@ -134,6 +135,7 @@ class Settings extends Component {
                             <div className="col-md-12">
                                 <StatsConfig
                                     interval={stats.interval}
+                                    customInterval={stats.customInterval}
                                     ignored={stats.ignored}
                                     enabled={stats.enabled}
                                     processing={stats.processingSetConfig}
@@ -166,6 +168,7 @@ Settings.propTypes = {
     stats: PropTypes.shape({
         processingGetConfig: PropTypes.bool,
         interval: PropTypes.number,
+        customInterval: PropTypes.number,
         enabled: PropTypes.bool,
         ignored: PropTypes.array,
         processingSetConfig: PropTypes.bool,
@@ -174,6 +177,7 @@ Settings.propTypes = {
     queryLogs: PropTypes.shape({
         enabled: PropTypes.bool,
         interval: PropTypes.number,
+        customInterval: PropTypes.number,
         anonymize_client_ip: PropTypes.bool,
         processingSetConfig: PropTypes.bool,
         processingClear: PropTypes.bool,
diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js
index 98bc99e2..c4739489 100644
--- a/client/src/helpers/constants.js
+++ b/client/src/helpers/constants.js
@@ -220,6 +220,12 @@ export const STATS_INTERVALS_DAYS = [DAY, DAY * 7, DAY * 30, DAY * 90];
 
 export const QUERY_LOG_INTERVALS_DAYS = [HOUR * 6, DAY, DAY * 7, DAY * 30, DAY * 90];
 
+export const RETENTION_CUSTOM = 1;
+
+export const RETENTION_CUSTOM_INPUT = 'custom_retention_input';
+
+export const CUSTOM_INTERVAL = 'customInterval';
+
 export const FILTERS_INTERVALS_HOURS = [0, 1, 12, 24, 72, 168];
 
 // Note that translation strings contain these modes (blocking_mode_CONSTANT)
@@ -462,6 +468,11 @@ export const UINT32_RANGE = {
     MAX: 4294967295,
 };
 
+export const RETENTION_RANGE = {
+    MIN: 1,
+    MAX: 365 * 24,
+};
+
 export const DHCP_VALUES_PLACEHOLDERS = {
     ipv4: {
         subnet_mask: '255.255.255.0',
diff --git a/client/src/reducers/queryLogs.js b/client/src/reducers/queryLogs.js
index 26d47025..89cc0041 100644
--- a/client/src/reducers/queryLogs.js
+++ b/client/src/reducers/queryLogs.js
@@ -1,7 +1,9 @@
 import { handleActions } from 'redux-actions';
 
 import * as actions from '../actions/queryLogs';
-import { DEFAULT_LOGS_FILTER, DAY } from '../helpers/constants';
+import {
+    DEFAULT_LOGS_FILTER, DAY, QUERY_LOG_INTERVALS_DAYS, HOUR,
+} from '../helpers/constants';
 
 const queryLogs = handleActions(
     {
@@ -59,6 +61,9 @@ const queryLogs = handleActions(
         [actions.getLogsConfigSuccess]: (state, { payload }) => ({
             ...state,
             ...payload,
+            customInterval: !QUERY_LOG_INTERVALS_DAYS.includes(payload.interval)
+                ? payload.interval / HOUR
+                : null,
             processingGetConfig: false,
         }),
 
@@ -95,6 +100,7 @@ const queryLogs = handleActions(
         anonymize_client_ip: false,
         isDetailed: true,
         isEntireLog: false,
+        customInterval: null,
     },
 );
 
diff --git a/client/src/reducers/stats.js b/client/src/reducers/stats.js
index 2e5a7e48..a1c63e14 100644
--- a/client/src/reducers/stats.js
+++ b/client/src/reducers/stats.js
@@ -1,6 +1,6 @@
 import { handleActions } from 'redux-actions';
 import { normalizeTopClients } from '../helpers/helpers';
-import { DAY } from '../helpers/constants';
+import { DAY, HOUR, STATS_INTERVALS_DAYS } from '../helpers/constants';
 
 import * as actions from '../actions/stats';
 
@@ -27,6 +27,9 @@ const stats = handleActions(
         [actions.getStatsConfigSuccess]: (state, { payload }) => ({
             ...state,
             ...payload,
+            customInterval: !STATS_INTERVALS_DAYS.includes(payload.interval)
+                ? payload.interval / HOUR
+                : null,
             processingGetConfig: false,
         }),
 
@@ -93,6 +96,7 @@ const stats = handleActions(
         processingStats: true,
         processingReset: false,
         interval: DAY,
+        customInterval: null,
         ...defaultStats,
     },
 );