Lovable moves updates to its own server and cuts data volume by roughly 97%
Lovable removed direct browser subscriptions to Firestore: they transmitted entire documents and required access rights to be maintained separately in the database and the API. Now a Go service checks permissions itself, assembles the response and sends changes over WebSocket. For example, once access is revoked, a member stops receiving project updates right in an open tab. By the team's estimate, the volume of transmitted data fell by roughly 97% compared with full responses.
AI-processed from Lovable Blog; edited by Hamidun News
Add an internal field to a project document, and the user's browser can already receive it. Lovable faced this risk while its frontend subscribed directly to Firestore documents. Developers had to think about the public API even when making an ordinary change to the database structure. And access rights had to be kept consistent in two places: the Firestore rules and the server-side Go code.
The team moved updates to its own service, Lovable Realtime. Now the server decides which fields to send to a particular user and revisits that decision whenever data or permissions change. According to Lovable, the service withstood a peak of 2.06 million concurrent subscriptions. The practical interest here lies in how the subscriptions are built, how permissions are checked, and how a live product was migrated.
What happens after access is revoked
Imagine a company workspace. An employee opened a project, then an administrator removed them from the group with access. The already open tab must stop receiving updates. When the set of permissions changes, the server may also need to remove individual fields from subsequent responses.
At Lovable, the access check was made a tracked data source just like the project itself. A subscription depends on both the project's contents and the user's permissions. A change in either dependency makes the server recompute the result available to the user. When access is revoked, the stream must close in the middle of a session.
This proved especially useful for enterprise groups: the necessary information lived in different databases, Firestore and Spanner. Firestore security rules could not read Spanner. A custom server layer made it possible to combine data from both databases in one response and apply the API's shared permission system.
However, this approach has a cost. At first, any change to a project document triggered a full permission recalculation, including ordinary file edits. The team kept recalculation only for changes to fields involved in the access decision. According to the team, the number of recalculations fell by roughly 84%. The list of such fields has to be maintained as part of the authorization logic; a separate static check helps find omissions in the packages it covers.
How updates reach the browser
Each tab gets one WebSocket connection, inside which several subscriptions run. Changes in Firestore and Spanner arrive through a change-capture mechanism at a bridge, then in NATS. The Go service receives the event and recomputes the affected subscriptions.
Next, it compares the hash of the new result with the previous one. If nothing changed for the user, there is nothing to send. If something did change, only the difference can be transmitted. Several interface components with the same subscription automatically share a single server-side subscription.
On reconnection, the browser sends a fingerprint of its saved state. The server rechecks permissions and loads current data. If the result matches, it confirms that the cache can be used without retransmitting the entire contents.
Over the 30 days covered in the article, the service delivered 2.61 billion frames of data and changes. The team estimated that hypothetically sending every computed result in full would have amounted to 40 TB. The volume actually transmitted was 1.11 TB, thanks to suppressing duplicates, sending diffs, and reusing state on reconnection. Hence the estimated reduction of roughly 97%. This is a comparison against a calculated baseline of full responses, not a measured reduction in Firestore costs.
What to take into your own product
The switchover began in shadow mode: the browser subscribed to the new service but kept displaying data from Firestore. This is how the team discovered waves of reconnections after deployments, failure classification errors, and a response size limit that was too small. The share of users was then increased in steps. According to Lovable, the migration went through without user-facing incidents.
One more detail matters for operations: adding servers does not offload long-lived connections that are already established. That is why Lovable limits the number of connections per service instance, keeps a memory reserve, and spreads out reconnections after a deployment over time.
Far from every team will need to build such a system from scratch. Here the choice was shaped by existing databases, a Go backend, and the requirement to change permissions during a session. But you can check your own product right now: which fields go to the browser, what happens after access is revoked, and whether the server withstands many tabs returning at once.
- Oct 15, 2026Lovable launches Deploy on AWS: apps and data move into the customer's VPC
- Nov 8, 2026Circle K Cuts Incident Triage from 45–60 Minutes to Under 15
- Oct 25, 2026Lovable Teaches Its AI to Promote Apps: Google and Meta Ads From the Chat
- Oct 24, 2026Lovable launches enterprise bundle: deployment to a customer's own AWS and Azure, EU inference, and policies
Key Questions Answered
What happens after access is revoked?
Imagine a company workspace. An employee opened a project, then an administrator removed them from the group with access. The already open tab must stop receiving updates. When the set of permissions changes, the server may also need to remove individual fields from subsequent responses. At Lovable, the access check was made a tracked data source just like the project itself. A subscription depends on both the project's contents and the user's permissions.
How updates reach the browser?
Each tab gets one WebSocket connection, inside which several subscriptions run. Changes in Firestore and Spanner arrive through a change-capture mechanism at a bridge, then in NATS. The Go service receives the event and recomputes the affected subscriptions. Next, it compares the hash of the new result with the previous one. If nothing changed for the user, there is nothing to send. If something did change, only the difference can be transmitted.
What to take into your own product?
The switchover began in shadow mode: the browser subscribed to the new service but kept displaying data from Firestore. This is how the team discovered waves of reconnections after deployments, failure classification errors, and a response size limit that was too small. The share of users was then increased in steps. According to Lovable, the migration went through without user-facing incidents.
Test Frontier LLMs & Autonomous Agents in One Workspace
Run Claude Opus 5.5, GPT-6, Gemini 3.1, and DeepSeek side-by-side in Nomad AI (nomadnet.ai) — unified model routing, deep research, and multimodal workflows under one subscription.
The AI world, distilled — once a week
Seven stories that actually mattered, hand-picked. No noise, no reposts, no press releases.
Done! Check your inbox for a confirmation.