diff --git a/src/matrixeventprocessor.ts b/src/matrixeventprocessor.ts
index a2ccedd3003c5b6192027088ba60698c621b9ced..d048eeec60d7702e2a48d45d1b40062c0b545928 100644
--- a/src/matrixeventprocessor.ts
+++ b/src/matrixeventprocessor.ts
@@ -210,6 +210,11 @@ export class MatrixEventProcessor {
             msg += `set the topic to \`${event.content!.topic}\``;
         } else if (event.type === "m.room.member") {
             const membership = event.content!.membership;
+            if (membership === "join") {
+                this.mxUserProfileCache.delete(`${event.room_id}:${event.sender}`);
+                // We don't know if the user also updated their profile, but to be safe..
+                this.mxUserProfileCache.delete(event.sender);
+            }
             if (membership === "join" && isNew && allowJoinLeave) {
                 msg += "joined the room";
             } else if (membership === "invite") {
@@ -365,29 +370,38 @@ export class MatrixEventProcessor {
         const intent = this.bridge.getIntent();
         let profile: {displayname: string, avatar_url: string} | undefined;
         try {
+            // First try to pull out the room-specific profile from the cache.
             profile = this.mxUserProfileCache.get(`${roomId}:${userId}`);
-            if (!profile) {
-                log.verbose(`Profile ${userId}:${roomId} not cached`);
-                profile = await mxClient.getStateEvent(roomId, "m.room.member", userId);
+            if (profile) {
+                return profile;
             }
+            log.verbose(`Profile ${userId}:${roomId} not cached`);
+
+            // Failing that, try fetching the state.
+            profile = await mxClient.getStateEvent(roomId, "m.room.member", userId);
             if (profile) {
                 this.mxUserProfileCache.set(`${roomId}:${userId}`, profile);
-            } else {
-                profile = this.mxUserProfileCache.get(`${userId}`);
+                return profile;
             }
-            if (!profile) {
-                log.verbose(`Profile ${userId} not cached`);
-                profile = await intent.getProfileInfo(userId);
-                if (profile) {
-                    this.mxUserProfileCache.set(`${userId}`, profile);
-                } else {
-                    log.warn(`User ${userId} has no member state and no profile. That's odd.`);
-                }
+
+            // Try fetching the users profile from the cache
+            profile = this.mxUserProfileCache.get(userId);
+            if (profile) {
+                return profile;
+            }
+
+            // Failing that, try fetching the profile.
+            log.verbose(`Profile ${userId} not cached`);
+            profile = await intent.getProfileInfo(userId);
+            if (profile) {
+                this.mxUserProfileCache.set(userId, profile);
+                return profile;
             }
+            log.warn(`User ${userId} has no member state and no profile. That's odd.`);
         } catch (err) {
             log.warn(`Trying to fetch member state or profile for ${userId} failed`, err);
         }
-        return profile;
+        return undefined;
     }
 
     private async sendReadReceipt(event: IMatrixEvent) {
@@ -419,7 +433,7 @@ export class MatrixEventProcessor {
 
     private async SetEmbedAuthor(embed: Discord.RichEmbed, sender: string, profile?: {
         displayname: string,
-        avatar_url: string} | undefined) {
+        avatar_url: string}) {
         let displayName = sender;
         let avatarUrl;
 
diff --git a/src/structures/timedcache.ts b/src/structures/timedcache.ts
index da16a18b9827aa05dfe45b81e7ea612cc1d07b70..03630cd984313f0a576676976f45ee40e6b0d2d8 100644
--- a/src/structures/timedcache.ts
+++ b/src/structures/timedcache.ts
@@ -62,16 +62,17 @@ export class TimedCache<K, V> implements Map<K, V> {
                 }
                 let item: IteratorResult<[K, ITimedValue<V>]>|undefined;
                 let filteredValue: V|undefined;
-                // Loop if => 1) no item/filteredvalue OR item && !filteredValue && not done
+                // Loop if we have no item, or the item has expired.
                 while (!item || filteredValue === undefined) {
                     item = iterator.next();
+                    // No more items in map. Bye bye.
                     if (item.done) {
                         break;
                     }
                     filteredValue = this.filterV(item.value[1]);
                 }
                 if (!item || filteredValue === undefined) {
-                    // Typscript doesn't like us returning undefined for valuel, which is dumb.
+                    // Typscript doesn't like us returning undefined for value, which is dumb.
                     // tslint:disable-next-line: no-any
                     return {done: true, value: undefined} as any as IteratorResult<[K, V]>;
                 }