diff --git a/package.json b/package.json
index 41c57d5..6bad3dc 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
   "author": "Adhidarma Hadiwinoto <me@adhisimon.org>",
   "license": "ISC",
   "dependencies": {
+    "redis": "^2.6.2",
     "request": "^2.74.0",
     "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git",
     "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git",
diff --git a/partner-fm.js b/partner-fm.js
index 80514bf..5852699 100644
--- a/partner-fm.js
+++ b/partner-fm.js
@@ -1,11 +1,14 @@
 var xml2js = require('xml2js');
 var request = require('request');
 var http = require('http');
+var redis = require('redis');
+var resendDelay = require('sate24/resend-delay.js')
 
 var aaa;
 var _callbackReport;
 var config;
 var logger;
+var redisClient;
 
 var xmlBuilder = new xml2js.Builder();
 
@@ -37,21 +40,34 @@ function start(options) {
         process.exit(1);
     }
 
+    createRedisClient(config.globals.redis_host, config.globals.redis_port);
     createServer();
 
-    /*
     resendDelay.init({
         config: config,
-        topupRequest: topupRequest,
+        topupRequest: topupStatus,
         logger: logger
     });
-    */
 }
 
 function topupRequest(task) {
     aaa.insertTaskToMongoDb(task);
 
-    var payload = composeTopupStatusMessage(
+    getTaskFromHistory(task, function(err, archivedTask) {
+        putTaskToHistory(task);
+
+        if (archivedTask) {
+            logger.info('Task has been executed before, going to checkStatus', {task: task, archivedTask: archivedTask});
+            topupStatus(task);
+        } else {
+            _topupRequest(task);
+        }
+    });
+}
+
+function _topupRequest(task) {
+
+    var payload = composeTopupMessage(
         config.h2h_out.pin,
         task.remoteProduct,
         task.destination,
@@ -64,20 +80,48 @@ function topupRequest(task) {
         body: payload,
         headers: {
             'Content-Type': 'text/xml',
-            //'Content-Length': Buffer.byteLength(payload)
         }
     };
 
-    logger.verbose('Requesting to partner', {reqOpts: reqOpts, payload: payload});
+    logger.verbose('Requesting TOPUP to partner', {reqOpts: reqOpts, payload: payload});
+    request(reqOpts, function (err, response, body) {
+        if (err) {
+            var msg = 'Error requesting TOPUP to partner: ' + err;
+            logger.warn(msg, {task: task, err: err});
+            callbackReport(task.requestId, '68', msg);
+            return;
+        }
+
+        logger.verbose('Got a direct response from TOPUP', {response: body, task: task});
+        topupResponseHandler(body, task.requestId, callbackReport);
+    });
+}
+
+function topupStatus(task) {
+    var payload = composeTopupStatusMessage(
+        config.h2h_out.pin,
+        task.requestId
+    );
+
+    var reqOpts = {
+        url: config.h2h_out.partner,
+        method: "POST",
+        body: payload,
+        headers: {
+            'Content-Type': 'text/xml',
+        }
+    };
+
+    logger.verbose('Requesting TOPUPSTATUS to partner', {reqOpts: reqOpts, payload: payload});
     request(reqOpts, function (err, response, body) {
         if (err) {
-            var msg = 'Error requesting to partner: ' + err;
+            var msg = 'Error requesting TOPUPSTATUS to partner: ' + err;
             logger.warn(msg, {task: task, err: err});
             callbackReport(task.requestId, '68', msg);
             return;
         }
 
-        logger.verbose('Got a direct response from partner', {response: body, task: task});
+        logger.verbose('Got a direct response from TOPUPSTATUS', {response: body, task: task});
         topupResponseHandler(body, task.requestId, callbackReport);
     });
 }
@@ -162,7 +206,7 @@ function modifyMessageWithSn(msg) {
     return msg;
 }
 
-function composeTopupStatusMessage(pin, product, destination, requestId) {
+function composeTopupMessage(pin, product, destination, requestId) {
     var data = {fm: {
         command: 'TOPUP',
         pin: pin,
@@ -174,6 +218,16 @@ function composeTopupStatusMessage(pin, product, destination, requestId) {
     return xmlBuilder.buildObject(data);
 }
 
+function composeTopupStatusMessage(pin, requestId) {
+    var data = {fm: {
+        command: 'TOPUPSTATUS',
+        pin: pin,
+        refTrxid: requestId
+    }}
+
+    return xmlBuilder.buildObject(data);
+}
+
 function createServer() {
     var httpServer = http.createServer(function(request, response) {
 
@@ -199,8 +253,119 @@ function createServer() {
     });
 }
 
+function createRedisClient(host, port) {
+    if (!host && !port) {
+        logger.info('Not creating redis client because unspecified host or port');
+        return;
+    }
+
+    try {
+        redisClient = redis.createClient(port, host);
+    } catch(err) {
+        logger.warn("Error creating redis client to " + host + ':' + port);
+    }
+}
+
+function getTaskKey(task, chipInfo) {
+    var requestId;
+
+    if (typeof task === 'string') {
+        requestId = task;
+    } else {
+        try {
+            requestId = task.requestId;
+        }
+        catch(e) {
+            logger.warn('Something wrong', {task: task});
+            console.trace('Cekidot');
+            process.exit(1);
+        }
+
+    }
+
+    if (!chipInfo && config && config.globals && config.globals.gateway_name) {
+        chipInfo = config.globals.gateway_name;
+    }
+
+    return chipInfo + '.hitachi.rid:' + requestId;
+}
+
+
+function putTaskToHistory(task, cb) {
+    if (Number(config.globals.no_dupe_check)) {
+        if (cb) { cb(); }
+        return;
+    }
+    var key = getTaskKey(task, config.globals.gateway_name);
+    logger.verbose('Saving task to history LRU', {key: key, task: task});
+
+    try {
+        taskHistory.set(key, JSON.parse(JSON.stringify(task)));
+    } catch (e) { }
+
+    putTaskToRedis(task, cb);
+}
+
+function putTaskToRedis(task, cb) {
+    if (!redisClient) {
+        logger.verbose('Not saving to redis because of undefined redisClient')
+        if (cb) { cb(); }
+        return;
+    }
+
+    var key = getTaskKey(task, config.globals.gateway_name);
+    logger.verbose('Saving task to redis', {key: key, task: task});
+
+    redisClient.set(key, JSON.stringify(task), function() {
+        redisClient.expire(key, 3600*24*30);
+        if (cb) {
+            cb();
+        }
+    });
+}
+
+function getTaskFromHistory(task, cb) {
+    logger.verbose('Getting task from history', {task: task});
+    var key = getTaskKey(task, config.globals.gateway_name);
+    var archive = taskHistory.get(key);
+
+    if (archive) {
+        if (cb) { cb(null, archive); }
+    }
+    else {
+        getTaskFromRedis(task, cb);
+    }
+}
+
+function getTaskFromRedis(task, cb) {
+    if (!redisClient) {
+        if (cb) { cb(null, null); }
+        return;
+    }
+
+    var key = getTaskKey(task, config.globals.gateway_name);
+    redisClient.get(key, function(err, result) {
+        if (err) {
+            logger.warn('Error retrieving task from redis', {err: err});
+            cb(err, null);
+            return;
+        }
+
+        var task;
+        try {
+            task = JSON.parse(result);
+        }
+        catch(e) {
+            logger.warn('Exception on parsing redis result as a json', {err: e});
+        }
+
+        cb(null, task);
+    })
+}
+
+
 exports.start = start;
 exports.topupRequest = topupRequest;
-exports.composeTopupStatusMessage = composeTopupStatusMessage;
+exports.composeTopupMessage = composeTopupMessage;
 exports.getSnFromMessage = getSnFromMessage;
 exports.modifyMessageWithSn = modifyMessageWithSn;