After you’ve instantiated the client-side PowerSync database, you will call connect() on it, which causes the PowerSync Client SDK to connect to the PowerSync Service for the purpose of syncing data to the client-side SQLite database, and to connect to your backend application as needed, for two potential purposes:
Purpose
Description
Uploading mutations to your backend:
Mutations that are made to the client-side SQLite database are uploaded to your backend application, where you control how they’re applied to your backend source database (Postgres, MongoDB, MySQL, or SQL Server). This is how PowerSync achieves bi-directional syncing of data: The PowerSync Service provides the server-to-client read path based on your Sync Streams or Sync Rules (legacy), and the client-to-server write path goes via your backend.
Authentication integration: (optional)
PowerSync uses JWTs for authentication between the Client SDK and PowerSync Service. Some authentication providers generate JWTs for users which PowerSync can verify directly. For others, some code must be added to your application backend to generate the JWTs.
Accordingly, you must pass a backend connector as an argument when you call connect() on the client-side PowerSync database. You must define that backend connector, and it must implement two functions/methods:
Purpose
Function
Description
Uploading mutations to your backend:
uploadData()
The PowerSync Client SDK automatically calls this function to upload client-side mutations to your backend. Whenever you write to the client-side SQLite database, those writes are also automatically placed into an upload queue by the Client SDK, and the Client SDK processes the entries in the upload queue by calling uploadData(). You should define your uploadData() function to call your backend application API to upload and apply the write operations to your backend source database. The Client SDK automatically handles retries in the case of failures. See Writing Data in the Client SDKs section for more details on the implementation of uploadData().
Authentication integration:
fetchCredentials()
Called by the PowerSync Client SDK to obtain a JWT and the endpoint URL for your PowerSync Service instance. The SDK uses the JWT to authenticate against the PowerSync Service. fetchCredentials() returns an object with token (JWT) and endpoint fields. See Authentication Setup for more details on JWT authentication.
Some authentication providers generate JWTs for users which PowerSync can verify directly, and in that case, your fetchCredentials() function implementation can simply return that JWT from client-side state. Your fetchCredentials() implementation only needs to retrieve a JWT from your backend if you are using Custom Authentication integration. See the Authentication Overview for more background.
The PowerSync Client SDK caches credentials internally and fetchCredentials is called in the following scenarios:
On initial connection - When connect() is called and no cached credentials are available.
Before the token expires - The PowerSync Service sends periodic keepalive messages that include the remaining lifetime of the current JWT. When the token has 30 seconds or less remaining, the SDK pre-fetches new credentials in the background to ensure a seamless transition.
When the token has expired - If the token expires (e.g. due to the device being offline), the SDK invalidates cached credentials and calls fetchCredentials() again when reconnecting.
On authentication errors - If the PowerSync Service responds with a 401 status, credentials are invalidated, prompting a fresh fetchCredentials() call on the next connection attempt.
For a JWT with a 1-hour expiry, fetchCredentials() is typically called approximately once per hour.
Your fetchCredentials() implementation should always return a fresh token when called, even if the currently cached token is not yet expired.
The SDK handles token rotation seamlessly regardless of the TTL, as long as fetchCredentials() can return a valid token when called.Avoid JWTs with a TTL shorter than 30 seconds, since the SDK’s pre-fetch threshold is 30 seconds - shorter TTLs would bypass pre-fetching and always hit the token-expired reconnection path.
If the JWT expires while the device is offline, the SDK handles reconnection automatically - it will call fetchCredentials() to obtain a new token when connectivity is restored.The PowerSync sync token is used exclusively for the connection between the Client SDK and the PowerSync Service. It is separate from your application’s own authentication session (e.g. Supabase Auth, Firebase Auth), which has its own lifecycle and refresh mechanism.