diff --git a/indra/llcommon/lleventfilter.cpp b/indra/llcommon/lleventfilter.cpp
index 1fd29ea9e5474c0c77a62c0fbbcab060a9a3a7e4..87eb583cb687dbfa1cc4e0cc8fcb9ec08a48b59e 100644
--- a/indra/llcommon/lleventfilter.cpp
+++ b/indra/llcommon/lleventfilter.cpp
@@ -198,6 +198,16 @@ bool LLEventBatch::post(const LLSD& event)
     return false;
 }
 
+void LLEventBatch::setSize(std::size_t size)
+{
+    mBatchSize = size;
+    // changing the size might mean that we have to flush NOW
+    if (mBatch.size() >= mBatchSize)
+    {
+        flush();
+    }
+}
+
 LLEventThrottle::LLEventThrottle(F32 interval):
     LLEventFilter("throttle"),
     mInterval(interval),
@@ -264,6 +274,45 @@ bool LLEventThrottle::post(const LLSD& event)
             mAlarm.actionAfter(timeRemaining, boost::bind(&LLEventThrottle::flush, this));
         }
     }
+    return false;
+}
+
+void LLEventThrottle::setInterval(F32 interval)
+{
+    F32 oldInterval = mInterval;
+    mInterval = interval;
+    // If we are not now within oldInterval of the last flush(), we're done:
+    // this will only affect behavior starting with the next flush().
+    F32 timeRemaining = mTimer.getRemainingTimeF32();
+    if (timeRemaining)
+    {
+        // We are currently within oldInterval of the last flush(). Figure out
+        // how much time remains until (the new) mInterval of the last
+        // flush(). Bt we don't actually store a timestamp for the last
+        // flush(); it's implicit. There are timeRemaining seconds until what
+        // used to be the end of the interval. Move that endpoint by the
+        // difference between the new interval and the old.
+        timeRemaining += (mInterval - oldInterval);
+        // If we're called with a larger interval, the difference is positive
+        // and timeRemaining increases.
+        // If we're called with a smaller interval, the difference is negative
+        // and timeRemaining decreases. The interesting case is when it goes
+        // nonpositive: when the new interval means we can flush immediately.
+        if (timeRemaining <= 0.0f)
+        {
+            flush();
+        }
+        else
+        {
+            // immediately reset mTimer
+            mTimer.setTimerExpirySec(timeRemaining);
+            // and if mAlarm is running, reset that too
+            if (mAlarm.running())
+            {
+                mAlarm.actionAfter(timeRemaining, boost::bind(&LLEventThrottle::flush, this));
+            }
+        }
+    }
 }
 
 LLEventBatchThrottle::LLEventBatchThrottle(F32 interval):
diff --git a/indra/llcommon/lleventfilter.h b/indra/llcommon/lleventfilter.h
index 1445b8a3b76236ae1c1293575691f8e3b3354aef..68890846a7aec7753bb79722629418394a020ae4 100644
--- a/indra/llcommon/lleventfilter.h
+++ b/indra/llcommon/lleventfilter.h
@@ -237,6 +237,10 @@ class LL_COMMON_API LLEventBatch: public LLEventFilter
     // accumulate an event and flush() when big enough
     virtual bool post(const LLSD& event);
 
+    // query or reset batch size
+    std::size_t getSize() const { return mBatchSize; }
+    void setSize(std::size_t size);
+
 private:
     LLSD mBatch;
     std::size_t mBatchSize;
@@ -289,6 +293,16 @@ class LL_COMMON_API LLEventThrottle: public LLEventFilter
     // register an event, may be either passed through or deferred
     virtual bool post(const LLSD& event);
 
+    // query or reset interval
+    F32 getInterval() const { return mInterval; }
+    void setInterval(F32 interval);
+
+    // deferred posts
+    std::size_t getPostCount() const { return mPosts; }
+
+    // time until next event would be passed through, 0.0 if now
+    F32 getDelay() const { return mTimer.getRemainingTimeF32(); }
+
 private:
     // remember throttle interval
     F32 mInterval;