diff --git a/synapse/events/__init__.py b/synapse/events/__init__.py
index 1ec79a67883918798c99764caaf01bb8ad2c0c2d..984f14fce457b4bd19e21f592b9c47c2a00b7e05 100644
--- a/synapse/events/__init__.py
+++ b/synapse/events/__init__.py
@@ -111,7 +111,7 @@ class EventBase(object):
 
 
 class FrozenEvent(EventBase):
-    def __init__(self, event_dict):
+    def __init__(self, event_dict, internal_metadata_dict={}):
         event_dict = copy.deepcopy(event_dict)
 
         signatures = copy.deepcopy(event_dict.pop("signatures", {}))
@@ -122,7 +122,8 @@ class FrozenEvent(EventBase):
         super(FrozenEvent, self).__init__(
             frozen_dict,
             signatures=signatures,
-            unsigned=unsigned
+            unsigned=unsigned,
+            internal_metadata_dict=internal_metadata_dict,
         )
 
     @staticmethod
diff --git a/synapse/storage/__init__.py b/synapse/storage/__init__.py
index 5c079da5bad0f1f376c65504eeb88e8ee416149f..26f205ae8ffdb133bdb0edf37c0551cad47654fc 100644
--- a/synapse/storage/__init__.py
+++ b/synapse/storage/__init__.py
@@ -156,12 +156,17 @@ class DataStore(RoomMemberStore, RoomStore,
             ]
         }
 
+        metadata_json =  encode_canonical_json(
+            event.internal_metadata.get_dict()
+        )
+
         self._simple_insert_txn(
             txn,
             table="event_json",
             values={
                 "event_id": event.event_id,
                 "room_id": event.room_id,
+                "internal_metadata": metadata_json.decode("UTF-8"),
                 "json": encode_canonical_json(event_dict).decode("UTF-8"),
             },
             or_replace=True,
diff --git a/synapse/storage/_base.py b/synapse/storage/_base.py
index 31d5163c1958290db4b1bf4341b1cd14356dcc6c..6dc857c4aa9f4c54930da64b6c01c00d81b06896 100644
--- a/synapse/storage/_base.py
+++ b/synapse/storage/_base.py
@@ -452,7 +452,7 @@ class SQLBaseStore(object):
     def _get_event_txn(self, txn, event_id, check_redacted=True,
                        get_prev_content=True):
         sql = (
-            "SELECT json, r.event_id FROM event_json as e "
+            "SELECT internal_metadata, json, r.event_id FROM event_json as e "
             "LEFT JOIN redactions as r ON e.event_id = r.redacts "
             "WHERE e.event_id = ? "
             "LIMIT 1 "
@@ -465,11 +465,12 @@ class SQLBaseStore(object):
         if not res:
             return None
 
-        js, redacted = res
+        internal_metadata, js, redacted = res
 
         d = json.loads(js)
+        internal_metadata = json.loads(internal_metadata)
 
-        ev = FrozenEvent(d)
+        ev = FrozenEvent(d, internal_metadata_dict=internal_metadata)
 
         if check_redacted and redacted:
             ev = prune_event(ev)
diff --git a/synapse/storage/schema/im.sql b/synapse/storage/schema/im.sql
index 0300bb29e1d32d5d6af78ce32c0a31dff9cc9f1d..253f9f779b91899d0e75c674219167255fcf01b6 100644
--- a/synapse/storage/schema/im.sql
+++ b/synapse/storage/schema/im.sql
@@ -36,6 +36,7 @@ CREATE INDEX IF NOT EXISTS events_room_id ON events (room_id);
 CREATE TABLE IF NOT EXISTS event_json(
     event_id TEXT NOT NULL,
     room_id TEXT NOT NULL,
+    internal_metadata NOT NULL,
     json BLOB NOT NULL,
     CONSTRAINT ev_j_uniq UNIQUE (event_id)
 );