diff --git a/lib/utils/fc-cache.js b/lib/utils/fc-cache.js
--- a/lib/utils/fc-cache.js
+++ b/lib/utils/fc-cache.js
@@ -33,6 +33,11 @@
     | Promise<?$ReadOnlyArray<NeynarChannel>>,
 };
 
+type QueuedChannelQuery = {
+  +channelID: string,
+  +resolve: (?NeynarChannel) => void,
+};
+
 class FCCache {
   client: NeynarClient;
 
@@ -50,6 +55,8 @@
     FollowedFarcasterChannelsQueryCacheEntry,
   > = new Map();
 
+  queuedChannelQueries: Array<QueuedChannelQuery> = [];
+
   constructor(client: NeynarClient) {
     this.client = client;
   }
@@ -186,6 +193,15 @@
     }
 
     const fetchFarcasterChannelPromise = (async () => {
+      let channelQuery;
+      const promise = new Promise<?NeynarChannel>(resolve => {
+        channelQuery = {
+          channelID,
+          resolve,
+        };
+        this.queuedChannelQueries.push(channelQuery);
+      });
+
       // First, we finish any ongoing fetches of followed channels,
       // since our channel might be one of them
       const fidsInFollowedChannelQueryCache = [
@@ -216,34 +232,106 @@
             if (channel.id !== channelID) {
               continue;
             }
+            this.queuedChannelQueries = this.queuedChannelQueries.filter(
+              possibleChannelQuery => possibleChannelQuery !== channelQuery,
+            );
             return channel;
           }
         }
       }
 
-      let farcasterChannel;
-      try {
-        farcasterChannel = await Promise.race([
-          this.client.fetchFarcasterChannelByID(channelID),
-          throwOnTimeout(`channel for ${channelID}`),
-        ]);
-      } catch (e) {
-        console.log(e);
-        return null;
+      if (this.queuedChannelQueries.length === 0) {
+        return promise;
       }
 
-      this.farcasterChannelQueryCache.set(channelID, {
-        channelID,
-        expirationTime: Date.now() + cacheTimeout,
-        farcasterChannel,
-      });
+      const channelQueries = this.queuedChannelQueries;
+      this.queuedChannelQueries = [];
+
+      const channelIDs = channelQueries.map(query => query.channelID);
+      const bulkQueryPromise = (async () => {
+        // If we only need to query for one, don't bother with the bulk API
+        if (channelIDs.length === 1) {
+          const [chanID] = channelIDs;
+
+          let farcasterChannel;
+          try {
+            farcasterChannel = await Promise.race([
+              this.client.fetchFarcasterChannelByID(chanID),
+              throwOnTimeout(`channel for ${chanID}`),
+            ]);
+          } catch (e) {
+            console.log(e);
+            return null;
+          }
+
+          this.farcasterChannelQueryCache.set(chanID, {
+            channelID: chanID,
+            expirationTime: Date.now() + cacheTimeout,
+            farcasterChannel,
+          });
+
+          return farcasterChannel ? [farcasterChannel] : [];
+        }
+
+        let farcasterChannels;
+        try {
+          farcasterChannels = await Promise.race([
+            this.client.fetchFarcasterChannelsByIDs(channelIDs),
+            throwOnTimeout(`channels for ${JSON.stringify(channelIDs)}`),
+          ]);
+        } catch (e) {
+          console.log(e);
+          return null;
+        }
+
+        const channelIDsInResultSet = new Set<string>();
+        for (const farcasterChannel of farcasterChannels) {
+          const chanID = farcasterChannel.id;
+          channelIDsInResultSet.add(chanID);
+          this.farcasterChannelQueryCache.set(chanID, {
+            channelID: chanID,
+            expirationTime: Date.now() + cacheTimeout,
+            farcasterChannel,
+          });
+        }
 
-      return farcasterChannel;
+        for (const chanID of channelIDs) {
+          if (!channelIDsInResultSet.has(chanID)) {
+            this.farcasterChannelQueryCache.set(chanID, {
+              channelID: chanID,
+              expirationTime: Date.now() + cacheTimeout,
+              farcasterChannel: undefined,
+            });
+          }
+        }
+
+        return farcasterChannels;
+      })();
+
+      for (const query of channelQueries) {
+        const { channelID: chanID, resolve } = query;
+        void (async () => {
+          const channels = await bulkQueryPromise;
+          if (!channels) {
+            resolve(null);
+            return;
+          }
+          for (const channel of channels) {
+            if (channel.id === chanID) {
+              resolve(channel);
+              return;
+            }
+          }
+          resolve(undefined);
+        })();
+      }
+
+      return promise;
     })();
 
     this.farcasterChannelQueryCache.set(channelID, {
       channelID,
-      expirationTime: Date.now() + queryTimeout * 2,
+      expirationTime: Date.now() + queryTimeout * 4,
       farcasterChannel: fetchFarcasterChannelPromise,
     });