diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 38c43cf61e17056d2fdc8cfc92bfb82dd7d71cad..da101d91e7fc1a8790c7981b9795e791f710e48f 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -6,6 +6,7 @@ Changelog
 -----
 
 * Colorized the output from the plugins.
+* Removed packet_cache argument from plugins, it is no longer needed.
 
 0.0.3
 -----
diff --git a/src/apex/__init__.py b/src/apex/__init__.py
index 62fb6348b48c4da4427689162f7e7ef0a8428b7f..d0608dd735dc42f018a031ceecec3907c2f49987 100644
--- a/src/apex/__init__.py
+++ b/src/apex/__init__.py
@@ -7,6 +7,7 @@ from __future__ import absolute_import
 from __future__ import division
 from __future__ import print_function
 
+from .nonrepeating_buffer import NonrepeatingBuffer  # noqa: F401
 from .util import echo_colorized_error  # noqa: F401
 from .util import echo_colorized_frame  # noqa: F401
 from .util import echo_colorized_warning  # noqa: F401
diff --git a/src/apex/cli.py b/src/apex/cli.py
index 72bb3202ef4dad27becb5d24acc7e75b036698ff..c6213c2a1a9d994c60adc9a42d2f6edd0d58fdbe 100644
--- a/src/apex/cli.py
+++ b/src/apex/cli.py
@@ -34,6 +34,7 @@ from apex.kiss import constants as kissConstants
 from apex.plugin_loader import get_plugins
 from apex.plugin_loader import load_plugin
 
+from .nonrepeating_buffer import NonrepeatingBuffer
 from .util import echo_colorized_error
 from .util import echo_colorized_frame
 from .util import echo_colorized_warning
@@ -138,7 +139,9 @@ def configure(configfile, verbose=False):
                 port_identifier = config.get(port_section, 'identifier')
                 port_net = config.get(port_section, 'net')
                 tnc_port = int(config.get(port_section, 'tnc_port'))
-                port_map[port_name] = {'identifier': port_identifier, 'net': port_net, 'tnc': aprs_tnc,
+                port_map[port_name] = {'identifier': port_identifier,
+                                       'net': port_net,
+                                       'tnc': NonrepeatingBuffer(aprs_tnc, port_name, tnc_port),
                                        'tnc_port': tnc_port}
 
     global aprsis
@@ -151,7 +154,8 @@ def configure(configfile, verbose=False):
             aprsis_password = -1
         aprsis_server = config.get('APRS-IS', 'server')
         aprsis_server_port = config.get('APRS-IS', 'server_port')
-        aprsis = apex.aprs.ReconnectingPacketBuffer(apex.aprs.IGate(aprsis_callsign, aprsis_password))
+        aprsis_base = apex.aprs.ReconnectingPacketBuffer(apex.aprs.IGate(aprsis_callsign, aprsis_password))
+        aprsis = NonrepeatingBuffer(aprsis_base, 'APRS-IS')
         aprsis.connect(aprsis_server, int(aprsis_server_port))
 
 
diff --git a/src/apex/nonrepeating_buffer.py b/src/apex/nonrepeating_buffer.py
new file mode 100644
index 0000000000000000000000000000000000000000..d58ea1acaf516f336831cd9cebee0f6b323c3838
--- /dev/null
+++ b/src/apex/nonrepeating_buffer.py
@@ -0,0 +1,53 @@
+# These imports are for python3 compatibility inside python2
+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+import threading
+import cachetools
+
+import apex.aprs.util
+
+
+class NonrepeatingBuffer(object):
+    def __init__(self, base_tnc, base_name, base_port=None, buffer_size=10000, buffer_time=30):
+        self.packet_cache = cachetools.TTLCache(buffer_size, buffer_time)
+        self.lock = threading.Lock()
+        self.base_tnc = base_tnc
+        self.base_port = base_port
+        self.base_name = base_name
+
+    @property
+    def port(self):
+        return self.base_port
+
+    @property
+    def name(self):
+        return self.base_name
+
+    def connect(self, *args, **kwargs):
+        self.base_tnc.connect(*args, **kwargs)
+
+    def close(self, *args, **kwargs):
+        self.base_tnc.close(*args, **kwargs)
+
+    def write(self, frame, *args, **kwargs):
+        with self.lock:
+            frame_hash = str(apex.aprs.util.hash_frame(frame))
+            if frame_hash not in self.packet_cache:
+                self.packet_cache[frame_hash] = frame
+                if self.base_port:
+                    self.base_tnc.write(frame, self.base_port)
+                else:
+                    self.base_tnc.write(frame)
+                apex.echo_colorized_frame(frame, self.base_name, False)
+
+    def read(self, *args, **kwargs):
+        with self.lock:
+            frame = self.base_tnc.read(*args, **kwargs)
+            if not frame:
+                return frame
+            frame_hash = str(apex.aprs.util.hash_frame(frame))
+            self.packet_cache[frame_hash] = frame
+            apex.echo_colorized_frame(frame, self.base_name, True)
+            return frame
diff --git a/src/apex/plugins/apexparadigm/__init__.py b/src/apex/plugins/apexparadigm/__init__.py
index 80387720ff889af8678a09210ca83821c79275f1..6a6abe50f6ef247f5f7085583b950e4329a408b4 100644
--- a/src/apex/plugins/apexparadigm/__init__.py
+++ b/src/apex/plugins/apexparadigm/__init__.py
@@ -6,9 +6,6 @@ from __future__ import print_function
 import copy
 import re
 
-import apex
-import apex.aprs.util
-
 __author__ = 'Jeffrey Phillips Freeman (WI2ARD)'
 __maintainer__ = 'Jeffrey Phillips Freeman (WI2ARD)'
 __email__ = 'jeffrey.freeman@syncleus.com'
@@ -85,64 +82,40 @@ class ApexParadigmPlugin(object):
                             if node == port['net']:
                                 frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] +\
                                                 [hop + '*'] + frame['path'][hop_index+1:]
-                                frame_hash = apex.aprs.util.hash_frame(frame)
-                                if frame_hash not in self.packet_cache.values():
-                                    self.packet_cache[str(frame_hash)] = frame_hash
-                                    port['tnc'].write(frame, port['tnc_port'])
-                                    self.aprsis.write(frame)
-                                    apex.echo_colorized_frame(frame, port_name, False)
+                                port['tnc'].write(frame, port['tnc_port'])
+                                self.aprsis.write(frame)
                                 return
                         else:
                             if port['net'].startswith(node):
                                 frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] +\
                                                 [hop + '*'] + frame['path'][hop_index+1:]
-                                frame_hash = apex.aprs.util.hash_frame(frame)
-                                if frame_hash not in self.packet_cache.values():
-                                    self.packet_cache[str(frame_hash)] = frame_hash
-                                    port['tnc'].write(frame, port['tnc_port'])
-                                    self.aprsis.write(frame)
-                                    apex.echo_colorized_frame(frame, port_name, False)
+                                port['tnc'].write(frame, port['tnc_port'])
+                                self.aprsis.write(frame)
                                 return
                     if node == port_callsign and ssid == port_ssid:
                         if ssid is 0:
                             frame['path'][hop_index] = port_callsign + '*'
                         else:
                             frame['path'][hop_index] = port['identifier'] + '*'
-                        frame_hash = apex.aprs.util.hash_frame(frame)
-                        if frame_hash not in self.packet_cache.values():
-                            self.packet_cache[str(frame_hash)] = frame_hash
-                            port['tnc'].write(frame, port['tnc_port'])
-                            self.aprsis.write(frame)
-                            apex.echo_colorized_frame(frame, port_name, False)
+                        port['tnc'].write(frame, port['tnc_port'])
+                        self.aprsis.write(frame)
                         return
                     elif node == 'GATE' and port['net'].startswith('2M'):
                         frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] + [node + '*'] +\
                                         frame['path'][hop_index+1:]
-                        frame_hash = apex.aprs.util.hash_frame(frame)
-                        if frame_hash not in self.packet_cache.values():
-                            self.packet_cache[str(frame_hash)] = frame_hash
-                            port['tnc'].write(frame, port['tnc_port'])
-                            self.aprsis.write(frame)
-                            apex.echo_colorized_frame(frame, port_name, False)
+                        port['tnc'].write(frame, port['tnc_port'])
+                        self.aprsis.write(frame)
                         return
                 if node.startswith('WIDE') and ssid > 1:
                     frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] +\
                         [node + '-' + str(ssid-1)] + frame['path'][hop_index+1:]
-                    frame_hash = apex.aprs.util.hash_frame(frame)
-                    if frame_hash not in self.packet_cache.values():
-                        self.packet_cache[str(frame_hash)] = frame_hash
-                        recv_port['tnc'].write(frame, recv_port['tnc_port'])
-                        self.aprsis.write(frame)
-                        apex.echo_colorized_frame(frame, port_name, False)
+                    port['tnc'].write(frame, port['tnc_port'])
+                    self.aprsis.write(frame)
                     return
                 elif node.startswith('WIDE') and ssid is 1:
                     frame['path'] = frame['path'][:hop_index] + [recv_port['identifier'] + '*'] + [node + '*'] + frame['path'][hop_index+1:]
-                    frame_hash = apex.aprs.util.hash_frame(frame)
-                    if frame_hash not in self.packet_cache.values():
-                        self.packet_cache[str(frame_hash)] = frame_hash
-                        recv_port['tnc'].write(frame, recv_port['tnc_port'])
-                        self.aprsis.write(frame)
-                        apex.echo_colorized_frame(frame, port_name, False)
+                    port['tnc'].write(frame, port['tnc_port'])
+                    self.aprsis.write(frame)
                     return
                 elif node.startswith('WIDE') and ssid is 0:
                     frame['path'][hop_index] = node + '*'
@@ -269,12 +242,8 @@ class ApexParadigmPlugin(object):
             else:
                 new_path += [hop]
         frame['path'] = new_path
-        frame_hash = apex.aprs.util.hash_frame(frame)
-        if frame_hash not in self.packet_cache.values():
-            self.packet_cache[str(frame_hash)] = frame_hash
-            selected_hop['port']['tnc'].write(frame, selected_hop['port']['tnc_port'])
-            self.aprsis.write(frame)
-            apex.echo_colorized_frame(frame, port_name, False)
+        port['tnc'].write(frame, port['tnc_port'])
+        self.aprsis.write(frame)
         return
 
     def stop(self):
diff --git a/src/apex/plugins/beacon/__init__.py b/src/apex/plugins/beacon/__init__.py
index 6cd7a24de12f0e5236a6c4700d56b80d79a0cfc1..b6da367221367bb9c3e17fd3b38d998eaee5da06 100644
--- a/src/apex/plugins/beacon/__init__.py
+++ b/src/apex/plugins/beacon/__init__.py
@@ -5,9 +5,6 @@ from __future__ import print_function
 
 import time
 
-import apex
-import apex.aprs.util
-
 __author__ = 'Jeffrey Phillips Freeman (WI2ARD)'
 __maintainer__ = 'Jeffrey Phillips Freeman (WI2ARD)'
 __email__ = 'jeffrey.freeman@syncleus.com'
@@ -72,10 +69,6 @@ class BeaconPlugin(object):
 
                     beacon_frame = {'source': port['identifier'], 'destination': 'APRS',
                                     'path': port['beacon_path'].split(','), 'text': port['beacon_text']}
-                    frame_hash = apex.aprs.util.hash_frame(beacon_frame)
-                    if frame_hash not in self.packet_cache.values():
-                        self.packet_cache[str(frame_hash)] = frame_hash
-                        port['tnc'].write(beacon_frame, port['tnc_port'])
-                        apex.echo_colorized_frame(beacon_frame, port_name, False)
+                    port['tnc'].write(beacon_frame, port['tnc_port'])
             else:
                 time.sleep(1)
diff --git a/src/apex/plugins/id/__init__.py b/src/apex/plugins/id/__init__.py
index c51c180fe7c96a9aff94375ff19f0269ea61d4e9..df6f4967b1121f157bbbc9b375a36585d8c19a24 100644
--- a/src/apex/plugins/id/__init__.py
+++ b/src/apex/plugins/id/__init__.py
@@ -5,9 +5,6 @@ from __future__ import print_function
 
 import time
 
-import apex
-import apex.aprs.util
-
 __author__ = 'Jeffrey Phillips Freeman (WI2ARD)'
 __maintainer__ = 'Jeffrey Phillips Freeman (WI2ARD)'
 __email__ = 'jeffrey.freeman@syncleus.com'
@@ -72,10 +69,6 @@ class IdPlugin(object):
 
                     id_frame = {'source': port['identifier'], 'destination': 'ID', 'path': port['id_path'].split(','),
                                 'text': port['id_text']}
-                    frame_hash = apex.aprs.util.hash_frame(id_frame)
-                    if frame_hash not in self.packet_cache.values():
-                        self.packet_cache[str(frame_hash)] = frame_hash
-                        port['tnc'].write(id_frame, port['tnc_port'])
-                        apex.echo_colorized_frame(id_frame, port_name, False)
+                    port['tnc'].write(id_frame, port['tnc_port'])
             else:
                 time.sleep(1)
diff --git a/src/apex/plugins/status/__init__.py b/src/apex/plugins/status/__init__.py
index 2391df5777efec58d48488826a945690eaf18157..d91beea5468756cc0a48c5fe0f60b18f89eb604b 100644
--- a/src/apex/plugins/status/__init__.py
+++ b/src/apex/plugins/status/__init__.py
@@ -5,9 +5,6 @@ from __future__ import print_function
 
 import time
 
-import apex
-import apex.aprs.util
-
 __author__ = 'Jeffrey Phillips Freeman (WI2ARD)'
 __maintainer__ = 'Jeffrey Phillips Freeman (WI2ARD)'
 __email__ = 'jeffrey.freeman@syncleus.com'
@@ -75,10 +72,6 @@ class StatusPlugin(object):
                         'destination': 'APRS',
                         'path': port['status_path'].split(','),
                         'text': port['status_text']}
-                    frame_hash = apex.aprs.util.hash_frame(status_frame)
-                    if frame_hash not in self.packet_cache.values():
-                        self.packet_cache[str(frame_hash)] = frame_hash
-                        port['tnc'].write(status_frame, port['tnc_port'])
-                        apex.echo_colorized_frame(status_frame, port_name, False)
+                    port['tnc'].write(status_frame, port['tnc_port'])
             else:
                 time.sleep(1)