8000 🚀 Feature: Realtime Query Listening · Issue #2490 · appwrite/appwrite · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

🚀 Feature: Realtime Query Listening #2490

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
2 tasks done
sanny-io opened this issue Dec 13, 2021 · 22 comments
Open
2 tasks done

🚀 Feature: Realtime Query Listening #2490

sanny-io opened this issue Dec 13, 2021 · 22 comments
Assignees
Labels
api / realtime Fixes and upgrades for the Appwrite Realtime API. backlog Issues waiting in the backlog

Comments

@sanny-io
Copy link

🔖 Feature description

Firebase allows you to actually listen to query results. If the results of your query would change if you ran it again, you are automatically given the latest results of your query in realtime.

https://firebase.google.com/docs/firestore/query-data/listen#listen_to_multiple_documents_in_a_collection

🎤 Pitch

This would allow realtime capabilities to be used with filters and offsets and such in a very simple manner.

👀 Have you spent some time to check if this issue has been raised before?

  • I checked and didn't find similar issue

🏢 Have you read the Code of Conduct?

@TorstenDittmann TorstenDittmann added the backlog Issues waiting in the backlog label Dec 15, 2021
@TorstenDittmann
Copy link
Contributor

Interesting idea, not sure about a possible implementation. Especially since our realtime server works with all services and resources of Appwrite - not just the Database.

Something like this is already possible with the current solution - just not out of the box and completely optimized.

I will keep this issue in the backlog for the future 🙏🏻

@eldadfux eldadfux added the api / realtime Fixes and upgrades for the Appwrite Realtime API. label Dec 21, 2021
@Re-Shard
Copy link

This is definitly an interesting feature. At this moment there are to few options to listen to changes on the DB.

@superseby2
Copy link

+1 adding filters to collection subscription would add a lot of flexiblity.

@stnguyen90
Copy link
Contributor
8000

Related discussion

@merabtenei
Copy link
merabtenei commented Sep 27, 2022

You can do that now but it's not straight forward.

make a listDocuments on a collection with some filters.
listen to changes on that collection
check if the payload corresponds to the previously set filters
update the list based on what event was received.

It would be great if we had something like in Firebase by doing all this on the background either on the server side or client side through the Sdk.

@Andrey253
Copy link

One of the solutions. I create collections by parameter name and write objects with the appropriate parameters to them. And I listen to collections with the parameters I need. If the parameter changes, delete the object and write it to another collection. I don't know how much I clearly put it.

@sanny-io
Copy link
Author

This could also be done on the client side ? You can do that now but it's not straight forward.

make a listDocuments on a collection with some filters.
listen to changes on that collection
check if the payload corresponds to the previously set filters
update the list based on what event was received.

Yes, the 3rd step is the crucial one that doesn't have a general solution with the current implementation.

I don't think this can be done on the client at all in a way that is scalable, especially not with limited resources on mobile devices.

One of the solutions. I create collections by parameter name and write objects with the appropriate parameters to them. And I listen to collections with the parameters I need. If the parameter changes, delete the object and write it to another collection. I don't know how much I clearly put it.

This is very clever, but would quickly grow unmanageable for more complex apps.

@DmitryGrigorov
Copy link
DmitryGrigorov commented Apr 25, 2023

The best idea to convert all sdk methods to REST API Queries and use axiosInstance.interceptors from axios npm package.

@ElmcHostedApplications
Copy link

This feature for realtime update based on query is needed. Example I may have a collections called States then I may have attributes called city, zip code, etc. In my React application I may have filters where I only want to subscribe to changes only if a zip code matches in the database

@WasserEsser
Copy link

This is a very necessary feature for realtime use.

Imagine a live-ticker scenario.
You have multiple simultaneously running games and a collection that will hold all the game events.

Subscribing to the collection means you get all events from all games, while you may only be interested in 1% or less of them. Pushing out all events to all clients has a huge impact on performance. The wasted bandwidth on both the server and the clients is unacceptable, so the Realtime feature of appwrite cannot be used.

Being able to apply queries to the subscription would eliminate this.

@merabtenei
Copy link
merabtenei commented May 25, 2023

@WasserEsser, that's not completely the case, each user will only receive updates from objects he has permission to view. With correct permission handling by your app, each user would receive only updates that he is granted to access, that may still be more than what you really need depending on the use case but IMO it's acceptable enough and realtime can indeed be used with proper permission management.

@WasserEsser
Copy link

@merabtenei You completely missed the point of my post. It's a live ticker. Anyone has and should have access to any game they want to see. Dynamically granting and revoking access based on which game you clicked on is not a solution, it's an awful dirty hack. If there is no way to do it properly, appwrite is not the solution for this use-case.

@xuelink
Copy link
Contributor
xuelink commented Sep 21, 2023

Up

@xuelink
Copy link
Contributor
xuelink commented Sep 21, 2023

@WasserEsser, that's not completely the case, each user will only receive updates from objects he has permission to view. With correct permission handling by your app, each user would receive only updates that he is granted to access, that may still be more than what you really need depending on the use case but IMO it's acceptable enough and realtime can indeed be used with proper permission management.

@merabtenei I asked this question today in discord live event like that are you planning to add this feature in future. They suggest me to use permissions as well. I dont have any deep experience with permissions but i think while creating a document, im able to put permission which is related exactly current user. If it works as expected, then no need to have this feature/issue. Websocket is going to send you only related updates.

@WasserEsser
Copy link
WasserEsser commented Sep 22, 2023

@WasserEsser, that's not completely the case, each user will only receive updates from objects he has permission to view. With correct permission handling by your app, each user would receive only updates that he is granted to access, that may still be more than what you really need depending on the use case but IMO it's acceptable enough and realtime can indeed be used with proper permission management.

@merabtenei I asked this question today in discord live event like that are you planning to add this feature in future. They suggest me to use permissions as well. I dont have any deep experience with permissions but i think while creating a document, im able to put permission which is related exactly current user. If it works as expected, then no need to have this feature/issue. Websocket is going to send you only related updates.

Again, this is not a solution. Using permissions to scope events should be done for their exact purpose, blocking people from receiving events they have no right to access, while in my case, they have every right to access them, they just don't want them.

This feature is very necessary.

@rohankm
Copy link
rohankm commented Oct 4, 2023

waiting for this feature

1 similar comment
@moshOntong-IT
Copy link

waiting for this feature

@moshOntong-IT
Copy link

Since realtime gives us a payload, but we would like to have something middleware or a filter method in Realtime subscribe that will have conditions something like for sample Query("consultType", "adasd"), then the server side will check it first if the payload contains this attribute then check if equal to this value. Since the realtime works with all service not only Database, but the thing is we have payload key from the Realtime response then we can use this. We can do this in client side, but it prefers that server side should handle this.

@jovazcode
Copy link

waiting for this feature

@asorokin
Copy link

Very much needed feature!

Permission management is not a solution here - just an ugly workaround.

Imagine a social media app where users subscribe to a collection of public posts. Every post is accessible to all users, and permissions allow everyone to read any document.

However, users only want to receive real-time updates for posts containing specific hashtags they care about (e.g., #Flutter, #Coding, #Games...). As the app and user base grow, client-side filtering becomes unmanageable due to excessive, unnecessary events, making it very poor for scalability.

Firebase already supports this. Why can't Appwrite add it too?

@sanny-io
Copy link
Author
sanny-io commented Jan 9, 2025

It would be more productive if we discussed possible implementations. I've recently been working with Prisma, which offers a service called Pulse.

Pulse is very similar to this feature request, as it allows you to write a query and stream rows in the database that match it. Pulse is not open source, so I decided to create my own version of it. My version uses Postgres' WAL feature, Kafka, and Debezium.

WebSocket clients connect and specify a query that they want to listen to. Whenever a database change occurs, my Kafka handler is ran, being given both the row and operation that is occurring (create, update, or delete).

For each condition in a query like equals, greaterThan, startsWith, etc, I created a handler. Most of the implementations for handlers was very simple. The more complex ones are the nots, ands, and ors, but those boil down to the simple ones anyways. Here's a few examples, trimmed down for brevity.

  equals: (columnValue, conditionValue) => {
    return columnValue === conditionValue
  },

  startsWith: (columnValue, conditionValue) => {
    return columnValue.startsWith(conditionValue)
  },

  contains: (columnValue, conditionValue) => {
    return columnValue.includes(conditionValue)
  },

  greaterThan: (columnValue, conditionValue) => {
    return columnValue > conditionValue
  },

Handlers are given the column's value, and the query's condition value. The handlers return whether the column's value conforms to the condition specified by the query.

If all handlers return true, then the WebSocket is notified of the row. This differs from Firestore, which notifies you of new query results rather than just rows that match those query results, but that behavior could be adjusted.

This isn't a perfect solution, but I just wanted to offer one that's worked for my needs in another library. I'm curious if others have input on this.

@akaco
Copy link
akaco commented Jan 14, 2025

Real-Time Query Subscriptions (Filtered Realtime) in Appwrite

Summary
Currently, Appwrite’s Realtime service only allows subscribing to entire collections or single documents, with no built-in way to filter by specific fields (e.g., WHERE orgId = 123 AND status = "active"). In many multi-tenant (SaaS) scenarios, subscribing to all documents in a collection can result in security and performance issues. We need a way to subscribe to documents matching a query so that each tenant/user only receives the relevant subset of events.

Real-World Example: SaaS with Multi-Tenant Data

Imagine a multi-tenant SaaS platform where each “tenant” is an organization. A typical database structure might look like this:

- Collection: tasks
- Fields:

  • -- organisationId (string)
  • -- title (string)
  • -- status (string: pending, done, etc.)

Since Appwrite currently doesn’t support query-based Realtime subscriptions, we only have these options:

1. Subscribe to the entire tasks collection

  • The client receives all task events for all organizations.
  • We must then filter out irrelevant tasks (organisationId !== currentOrg).
  • This creates overhead on bandwidth and also risks exposing sensitive data (even if only momentarily) to clients who shouldn’t see it.

2. Subscribe to each task individually (by ID)

  • This is not scalable if you have hundreds or thousands of tasks, or if new tasks are constantly being created.

Both approaches are problematic in a real-world SaaS environment.

Why We Need Real-Time Query Subscriptions

  1. Security
  • Even if we only store the relevant tasks client-side, the raw Realtime payload might momentarily expose other tenants’ data.
  • Relying on the client to discard irrelevant data is risky.A single bug or malicious tweak on the front end could leak data.
  • True multi-tenant isolation requires restricting data at the server side—before sending it over the wire.
  1. Performance & Bandwidth
  • Larger collections will flood the client with events. For example, a busy system with thousands of tasks triggers constant Realtime events that might not even be relevant to the user.
  • If we could subscribe only to WHERE organisationId = "<someId>", it dramatically reduces overhead for both the server and the client.
  1. Cleaner Client Code
  • Currently, we juggle custom filtering logic in the subscription callback. This leads to extra complexity, potential bugs, and more fragile code.
  • Query-based Realtime would allow us to define the logic in one place—on Appwrite’s side—ensuring consistent behavior across all clients.

Desired API / Feature Proposal

A potential approach could look like:

js
// Hypothetical example
client.subscribe<Models.Document>(
  `databases.${dbId}.collections.${colId}.documents`, 
  {
    queries: [
      Query.equal('organisationId', currentOrg),
      Query.notEqual('status', 'deleted'),
    ]
  },
  (response) => {
    // Only events matching the query are sent here
    console.log('Received real-time event:', response);
  }
);

In this scenario:

  • Server-Side Filtering: Appwrite would evaluate these queries for each doc event. If a doc doesn’t match the condition, no event is sent to the client.
  • Security: This prevents any data “leak” to unauthorized clients.
  • Performance: Clients only receive relevant updates, drastically reducing traffic and processing.

Why It’s Urgent for Many SaaS Apps

When building a multi-tenant SaaS, real-time updates are a core user experience feature. For example, a team board or project management app that shows tasks in real time for each organization. Without query-based filtering, devs must either:

  • Subscribe to all data and risk exposing other tenants’ tasks.
  • Or subscribe to each doc individually, which is unmanageable at scale.

A proper, server-side Realtime query filter is essential for secure and efficient multi-tenant architectures.

Shout-Out
@TorstenDittmann (and the rest of the Appwrite team): This feature would greatly improve the developer experience for SaaS apps built on Appwrite. It aligns with the principle that data should only be delivered if it meets a user’s permission criteria. Right now, we rely on client-side filtering, which poses both security and performance challenges.

We appreciate the amazing work on Appwrite so far and hope you’ll consider adding Real-Time Query Subscriptions to the roadmap. It would be a game-changer for many production use cases.

Thank you for reviewing this request!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api / realtime Fixes and upgrades for the Appwrite Realtime API. backlog Issues waiting in the backlog
Projects
None yet
Development

No branches or pull requests

0