Replies: 1 comment 1 reply
-
Hi, please post short discussion topics not long AI whatever. I'm not sure what this is all about. |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Introduction
ElectricSQL is a local-first Postgres synchronization engine that uses shapes to define subsets of data for replication to clients. A shape typically targets a single Postgres table and may include filters to limit columns or rows, thereby allowing applications to sync only the necessary data. Because ElectricSQL replicates database content to client devices that may be untrusted, ensuring robust security in the data synchronization process is critical. This article focuses on security concerns—particularly the limitations of shapes for relational security—and also discusses related issues around extensibility and developer experience. While performance is not a primary concern in this discussion, the ability to securely and flexibly manage data syncs is central to ElectricSQL’s production-readiness, especially for multi-user applications.
Security Concerns in Shapes
Lack of Relational Security Features
ElectricSQL shapes currently offer limited support for expressing complex, relational access rules. Specifically, a shape’s filtering mechanism is confined to the target table’s columns and does not support joins or subqueries involving other tables. In many real-world applications, data access must be restricted based on relationships between tables. For instance, when syncing a table like
LIST_ITEMS
, a row-level restriction based on a user’s ID (derived from a many-to-many relationship) cannot be directly encoded into a shape. This gap forces developers to implement external logic—such as adding a parameter (e.g.,restrict_user=user_id
) that a proxy enforces—to achieve relational security. However, relying on external mechanisms increases the risk of misconfiguration and potential security breaches.Workaround with Proxy Filtering
A common workaround is to use an authorization proxy that intercepts shape requests, verifies the user's identity, and injects additional filters to ensure only authorized data is returned. For example, a proxy might alter a shape query to include a clause like
WHERE user_id IN (...)
based on an initial query to an N-to-N relationship table. Although this approach can enforce a form of row-level security, it creates complications. The dynamic alteration of a shape’s filter effectively changes the shape’s definition. This is problematic for the PGlite extension, which expects the shape configuration (orshapeKey
) to remain consistent over time. Once the filter changes, the client’s sync state may become invalid, making this approach feasible only if the underlying relational data remains immutable.Issues with Shape State in PGlite
The PGlite extension for ElectricSQL enforces a one-shape-per-table policy on the client side. When a shape’s filter is dynamically altered (for example, through a proxy’s injection of user-specific parameters), the shape is effectively redefined. This leads to state inconsistencies: data synced under one shape configuration may become invalid once the shape is altered. The client is then forced to discard and re-sync the data, an inefficient process that complicates application logic. As a result, while proxy filtering can restrict data access, it undermines the seamless synchronization ElectricSQL aims to provide and introduces substantial overhead for multi-user scenarios.
View-Based Solution
An alternative solution involves creating a database view that pre-joins or filters data to reflect the desired permissions (e.g., a view named
LIST_ITEMS_PERMISSION
that mergesLIST_ITEMS
with the appropriate relational data). By subscribing to a view instead of the base table, developers can offload the complex filtering logic to the database layer. However, this method comes with its own set of challenges:Overall, while views can provide a temporary fix for enforcing relational security, they increase both project complexity and the risk of subtle bugs.
Challenges in Managing Multiple Shapes
One Shape Per Table Restriction
ElectricSQL currently enforces a one-shape-per-table rule on the client side. This design simplifies state management and ensures consistency, but it poses problems when an application requires multiple views on the same underlying data. For example, an app might need one shape for the current user’s data and another shape to represent a subset of users related through shared
LIST_ITEMS
. Since ElectricSQL restricts a table to a single shape, developers must either merge these views into one shape (risking data overexposure) or handle dynamic unsubscription and re-subscription of shapes—each of which adds complexity to the client logic.Syncing Complexity
The inability to have multiple active shapes for a single table forces developers into a pattern of frequently discarding and re-syncing data as user contexts change. This not only affects performance but also complicates the state management logic on the frontend. Developers must carefully orchestrate when and how to swap shape subscriptions, ensure that stale data is purged, and mitigate any potential UI disruption during transitions. This complexity further magnifies the risk of accidentally exposing data or introducing synchronization bugs.
Backend Data Restriction Challenges
Enforcing Data Access Control
By default, ElectricSQL’s sync service uses a standard Postgres database account with broad read permissions. This means that any shape subscribed by a client will return all data that the database account can access. In multi-user applications, this model is problematic because it relies on external mechanisms (e.g., API gateways or proxies) to enforce user-specific data restrictions. Although ElectricSQL already supports PostgreSQL Row-Level Security, the challenge remains in ensuring that session-based data is correctly and dynamically injected into the sync process so that RLS policies are enforced without relying on client-supplied parameters. Without a built-in mechanism to securely tie the client’s identity to the sync session, developers must continue to implement additional safeguards to prevent unauthorized data access.
Injecting Secure Session Data
Even though ElectricSQL supports PostgreSQL Row-Level Security, ensuring that the correct session context is applied to each sync request remains a challenge. Ideally, the sync service should determine the user's identity from a secure session token on the backend rather than trusting a client-provided parameter. This secure injection would ensure that RLS policies are applied correctly and that clients cannot manipulate query filters to gain access to data they shouldn’t see. At present, the integration of session-based context into the shape subscription process is not as seamless as it could be, requiring developers to build additional safeguards externally.
Preventing Query Manipulation
The current model requires that clients send shape definitions—including potentially sensitive filtering parameters—over HTTP. Without additional safeguards, a malicious client could alter these parameters to access unauthorized data. A secure solution would be to have the backend validate or completely override the client-supplied filters based on the authenticated session. This could be achieved by enforcing a policy where only predefined or server-approved shapes are permitted, effectively removing any dynamic query manipulation by the client. Until such a feature is integrated, the onus remains on developers to deploy ElectricSQL behind a robust, secure API layer.
Extensibility Concerns
Overriding the Transport Mode
ElectricSQL currently relies on a fetch-based HTTP transport for synchronizing shapes between the proxy and the client. While this single transport approach simplifies core development and allows the ElectricSQL team to concentrate on a stable, robust implementation, it limits flexibility. Rather than expanding the official scope to include native support for alternative protocols, the architecture should be designed so that the transport layer is overridable. This would allow third-party developers to substitute the default fetch client with their own implementations (such as WebSocket or Protocol Buffers) without diluting the project's focus. In other words, the ElectricSQL team should maintain focus on one robust transport mechanism while providing well-defined hooks or interfaces for others to implement alternative protocols.
Backoff Implementation Issues
The current ElectricSQL client permits configuration of retry and timeout parameters for its backoff strategy, offering some level of customization. However, this parameterization only allows developers to adjust specific values rather than to substitute or extend the entire backoff implementation. For finer control—especially in environments with unique network behaviors such as Safari on iOS—it would be beneficial to expose a mechanism for overriding the complete backoff logic. This means that rather than just passing parameters (e.g., maximum delay or jitter), developers should be able to provide a custom backoff function or handler that implements the full reconnection strategy. Such flexibility would allow the community to implement granular, environment-specific backoff behaviors without waiting for official changes.
Conclusion
ElectricSQL’s shape-based synchronization model provides a compelling approach for local-first applications, but it currently faces significant challenges in the realms of security and extensibility. The inability of shapes to enforce relational security without relying on external proxies, combined with the restrictions on managing multiple views per table, places a substantial burden on developers. Additionally, even though ElectricSQL supports PostgreSQL Row-Level Security, the process of injecting secure session data and ensuring it is correctly applied to each sync session needs refinement to prevent unauthorized data access.
From an extensibility perspective, while the core HTTP transport and configurable backoff parameters are solid foundations, the architecture would benefit from allowing developers to override the transport layer and fully replace the backoff implementation when needed. Such flexibility would enable integrations with alternative protocols and provide more granular control over connection behaviors—all while letting the ElectricSQL team maintain focus on a single, robust transport solution.
Recommendations
Based on the analysis above, the following steps are recommended for the ElectricSQL team and contributors:
Enhance Fine-Grained Security:
Support Multiple Shapes per Table:
Allow Overriding Core Components:
Prevent Query Manipulation:
In summary, while ElectricSQL represents a significant step forward in local-first data synchronization, addressing these security and extensibility challenges is crucial for its adoption in production environments. By refining the integration of session-based security and providing extensibility hooks for transport and reconnection logic, ElectricSQL can offer a safer, more flexible solution for developers building multi-user applications.
Beta Was this translation helpful? Give feedback.
All reactions