diff --git a/crates/grafana-plugin-sdk/examples/main.rs b/crates/grafana-plugin-sdk/examples/main.rs
index 4de5d81b..7444c369 100644
--- a/crates/grafana-plugin-sdk/examples/main.rs
+++ b/crates/grafana-plugin-sdk/examples/main.rs
@@ -56,13 +56,16 @@ impl backend::DataQueryError for QueryError {
 impl backend::DataService for MyPluginService {
     type Query = Query;
     type QueryError = QueryError;
-    type Stream = backend::BoxDataResponseStream<Self::QueryError>;
-    async fn query_data(&self, request: backend::QueryDataRequest<Self::Query>) -> Self::Stream {
+    type Stream<'a> = backend::BoxDataResponseStream<'a, Self::QueryError>;
+    async fn query_data<'st, 'r: 'st, 's: 'r>(
+        &'s self,
+        request: &'r backend::QueryDataRequest<Self::Query>,
+    ) -> Self::Stream<'st> {
         Box::pin(
             request
                 .queries
-                .into_iter()
-                .map(|x: DataQuery<Self::Query>| async move {
+                .iter()
+                .map(|x: &DataQuery<Self::Query>| async move {
                     // We can see the user's query in `x.query`:
                     debug!(
                         expression = x.query.expression,
@@ -88,7 +91,7 @@ impl backend::DataService for MyPluginService {
                         .into_frame("foo")
                         .check()
                         .map_err(|source| QueryError {
-                            ref_id: x.ref_id,
+                            ref_id: x.ref_id.clone(),
                             source,
                         })?],
                     ))
diff --git a/crates/grafana-plugin-sdk/src/backend/data.rs b/crates/grafana-plugin-sdk/src/backend/data.rs
index d65b7975..4d869710 100644
--- a/crates/grafana-plugin-sdk/src/backend/data.rs
+++ b/crates/grafana-plugin-sdk/src/backend/data.rs
@@ -191,7 +191,7 @@ pub trait DataQueryError: std::error::Error {
 ///     ///
 ///     /// In general the concrete type will be impossible to name in advance,
 ///     /// so the `backend::BoxDataResponseStream` type alias will be useful.
-///     type Stream = backend::BoxDataResponseStream<Self::QueryError>;
+///     type Stream<'a> = backend::BoxDataResponseStream<'a, Self::QueryError>;
 ///
 ///     /// Respond to a request for data from Grafana.
 ///     ///
@@ -201,7 +201,7 @@ pub trait DataQueryError: std::error::Error {
 ///     ///
 ///     /// Our plugin must respond to each query and return an iterator of `DataResponse`s,
 ///     /// which themselves can contain zero or more `Frame`s.
-///     async fn query_data(&self, request: backend::QueryDataRequest<Self::Query>) -> Self::Stream {
+///     async fn query_data(&self, request: backend::QueryDataRequest<Self::Query>) -> Self::Stream<'_> {
 ///         Box::pin(
 ///             request
 ///                 .queries
@@ -246,18 +246,23 @@ pub trait DataService {
     ///
     /// This will generally be impossible to name directly, so returning the
     /// [`BoxDataResponseStream`] type alias will probably be more convenient.
-    type Stream: Stream<Item = Result<DataResponse, Self::QueryError>> + Send;
+    type Stream<'a>: Stream<Item = Result<DataResponse, Self::QueryError>> + Send + 'a
+    where
+        Self: 'a;
 
     /// Query data for an input request.
     ///
     /// The request will contain zero or more queries, as well as information about the
     /// origin of the queries (such as the datasource instance) in the `plugin_context` field.
-    async fn query_data(&self, request: QueryDataRequest<Self::Query>) -> Self::Stream;
+    async fn query_data<'st, 's: 'st>(
+        &'s self,
+        request: QueryDataRequest<Self::Query>,
+    ) -> Self::Stream<'st>;
 }
 
 /// Type alias for a boxed iterator of query responses, useful for returning from [`DataService::query_data`].
-pub type BoxDataResponseStream<E> =
-    Pin<Box<dyn Stream<Item = Result<backend::DataResponse, E>> + Send>>;
+pub type BoxDataResponseStream<'a, E> =
+    Pin<Box<dyn Stream<Item = Result<backend::DataResponse, E>> + Send + 'a>>;
 
 /// Serialize a slice of frames to Arrow IPC format.
 ///
diff --git a/crates/grafana-plugin-sdk/src/backend/mod.rs b/crates/grafana-plugin-sdk/src/backend/mod.rs
index d39fc0a6..3f428ec0 100644
--- a/crates/grafana-plugin-sdk/src/backend/mod.rs
+++ b/crates/grafana-plugin-sdk/src/backend/mod.rs
@@ -74,7 +74,7 @@ impl backend::DataService for MyPlugin {
     ///
     /// In general the concrete type will be impossible to name in advance,
     /// so the `backend::BoxDataResponseStream` type alias will be useful.
-    type Stream = backend::BoxDataResponseStream<Self::QueryError>;
+    type Stream<'a> = backend::BoxDataResponseStream<'a, Self::QueryError>;
 
     /// Respond to a request for data from Grafana.
     ///
@@ -279,7 +279,7 @@ impl ShutdownHandler {
 ///     ///
 ///     /// In general the concrete type will be impossible to name in advance,
 ///     /// so the `backend::BoxDataResponseStream` type alias will be useful.
-///     type Stream = backend::BoxDataResponseStream<Self::QueryError>;
+///     type Stream<'a> = backend::BoxDataResponseStream<'a, Self::QueryError>;
 ///
 ///     /// Respond to a request for data from Grafana.
 ///     ///
diff --git a/crates/grafana-plugin-sdk/src/backend/noop.rs b/crates/grafana-plugin-sdk/src/backend/noop.rs
index 8b1eb798..3aa66047 100644
--- a/crates/grafana-plugin-sdk/src/backend/noop.rs
+++ b/crates/grafana-plugin-sdk/src/backend/noop.rs
@@ -30,8 +30,11 @@ impl DataQueryError for Infallible {
 impl DataService for NoopService {
     type Query = ();
     type QueryError = Infallible;
-    type Stream = BoxDataResponseStream<Self::QueryError>;
-    async fn query_data(&self, _request: QueryDataRequest<Self::Query>) -> Self::Stream {
+    type Stream<'a> = BoxDataResponseStream<'static, Self::QueryError>;
+    async fn query_data<'st, 's: 'st>(
+        &'s self,
+        _request: QueryDataRequest<Self::Query>,
+    ) -> Self::Stream<'st> {
         unreachable!()
     }
 }