# How to Configure Apache Sedona SQL Engine for Spatial SQL Queries in the Browser

> Configure Apache Sedona SQL for in-browser spatial SQL queries with GeoLibre. Leverage WebAssembly for fast local processing or Python fallback, handling up to 50,000 features automatically.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: how-to-guide
- Published: 2026-08-02

---

**GeoLibre provides a dual-engine architecture that runs Apache Sedona spatial SQL directly in the browser via WebAssembly (CereusDB) or falls back to a Python side-car, with automatic detection and a 50,000 feature limit for in-browser processing.**

The open-source GeoLibre project enables advanced geospatial analytics without server infrastructure by embedding the Apache Sedona SQL engine directly into web applications. This guide explains how to configure the system to execute spatial SQL queries using either the Rust-backed WebAssembly runtime or an optional Python side-car for larger datasets.

## Understanding the Dual-Engine Architecture

GeoLibre ships two implementations of the Apache Sedona spatial-SQL engine:

- **CereusDB (WebAssembly)**: Runs directly in the browser via [`sedona-workspace.ts`](https://github.com/opengeos/GeoLibre/blob/main/sedona-workspace.ts) as a Rust-backed, WASM-compiled version of SedonaDB.
- **SedonaDB Side-car (Python)**: Runs as a FastAPI process on the client machine defined in [`sedona_ops.py`](https://github.com/opengeos/GeoLibre/blob/main/sedona_ops.py).

When the side-car is reachable, the UI prefers it for larger data volumes and native raster support. If unavailable, the browser automatically falls back to CereusDB according to the routing logic in `runSedonaQuery`.

## How the In-Browser Engine Works

### Loading the WASM Bundle

The first call to any Sedona query triggers `loadCereusDb()` in [`apps/geolibre-desktop/src/lib/sedona-workspace.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/lib/sedona-workspace.ts). This fetches the compiled `cereus.wasm` file and creates a singleton `CereusInstance` (stored as `dbPromise`).

### Registering Spatial Layers

Every GeoJSON layer in the current map is converted into a source table via `registerGeoJSON` and exposed as a view that parses the geometry column with `ST_GeomFromText`. This registration happens in `registerLayerTables` within the same module.

### Feature Count Limits

The browser engine enforces a hard cap of **50,000 features** per layer (`MAX_CEREUS_FEATURES`). Exceeding this limit throws an error and prompts the user to use the side-car instead.

### Query Execution and Routing

The `runSedonaQuery` function sanitizes statements using `cleanStatement`, checks for multiple statements, and executes via either `runCereusQuery` (in-browser) or `runSidecarQuery` (Python). Side-car availability is probed via `/sql/status` and cached for 5 seconds (`SIDECAR_PROBE_TTL_MS`).

## Step-by-Step Configuration for Pure Browser Use

1. **Ensure WASM Bundle Accessibility**: The build includes `cereus.wasm` by default. The bundle loads relative to the app's base URL with no additional network configuration required.

2. **Disable Side-Car Detection**: For web-only deployments, ensure the Python server is not running. Desktop builds set `IS_MAS_BUILD` to `true` for Mac App Store compatibility, which disables side-car probes.

3. **Initialize the Engine**: Import and call `runSedonaQuery` from your UI code. The first call lazily loads the WASM bundle automatically.

4. **Monitor Data Volume**: Keep individual layers below 50,000 features. Split larger datasets into multiple layers or use the desktop app with the side-car enabled.

## Optional: Enabling the Python Side-Car for Larger Datasets

To process datasets exceeding browser limits:

1. Install the Sedona package:

```bash
pip install "apache-sedona[db]"

```

2. Start the FastAPI side-car using the convenience script [`python/hatch_build.py`](https://github.com/opengeos/GeoLibre/blob/main/python/hatch_build.py) in the repository to build the wheel and launch `geolibre_server`.

3. Verify the health endpoint:

```bash
curl http://127.0.0.1:8765/sql/status

```

A successful response returns `"available": true`.

4. The `runSedonaQuery` function automatically routes queries to the side-car when detected, as implemented in [`sedona-workspace.ts`](https://github.com/opengeos/GeoLibre/blob/main/sedona-workspace.ts).

## Code Examples

### Running a Simple Spatial Query

```typescript
import { runSedonaQuery } from '@geolibre/processing';

const sql = `
  SELECT name, ST_Area(geometry) AS area_m2
  FROM my_layer
  WHERE ST_Intersects(geometry, ST_MakeEnvelope(-120, 35, -119, 36, 4326))
`;

runSedonaQuery(sql, layers)
  .then(result => {
    console.table(result.rows);
    // result.geojson contains a FeatureCollection for mapping
  })
  .catch(err => console.error('Sedona query failed:', err));

```

### Forcing In-Browser Execution

```typescript
import { IS_MAS_BUILD } from './build-flags';

// Bypass side-car probe for testing
(IS_MAS_BUILD as any) = true;
await runSedonaQuery(sql, layers);

```

### Handling Feature Limit Errors

```typescript
try {
  await runSedonaQuery(sql, layers);
} catch (e) {
  if (e.message.includes('exceeding the 50000-feature limit')) {
    console.error('Switch to side-car for large datasets');
  }
}

```

## Key Configuration Files

| File | Role |
|------|------|
| [`apps/geolibre-desktop/src/lib/sedona-workspace.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/lib/sedona-workspace.ts) | Core engine loader, layer registration, and query routing logic |
| [`backend/geolibre_server/geolibre_server/sedona_ops.py`](https://github.com/opengeos/GeoLibre/blob/main/backend/geolibre_server/geolibre_server/sedona_ops.py) | Python side-car wrapping `apache-sedona[db]` |
| [`backend/geolibre_server/geolibre_server/app/sql.py`](https://github.com/opengeos/GeoLibre/blob/main/backend/geolibre_server/geolibre_server/app/sql.py) | FastAPI endpoints exposing SedonaDB over HTTP |
| [`apps/geolibre-desktop/src/lib/sql-workspace.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/lib/sql-workspace.ts) | Statement sanitization and result normalization |

## Summary

- GeoLibre offers two Apache Sedona engines: CereusDB (WASM/browser) and SedonaDB (Python side-car).
- The browser engine limits layers to 50,000 features (`MAX_CEREUS_FEATURES`) and lazy-loads via `loadCereusDb()`.
- Side-car availability is detected via `/sql/status` with a 5-second cache (`SIDECAR_PROBE_TTL_MS`).
- Configure pure-browser mode by ensuring the WASM bundle is present and the side-car is unreachable.
- For large datasets, install `apache-sedona[db]` and launch the FastAPI server to automatically upgrade query capacity.

## Frequently Asked Questions

### What is the maximum number of features the browser can process?

The in-browser CereusDB engine limits single layers to 50,000 features as defined by `MAX_CEREUS_FEATURES` in [`sedona-workspace.ts`](https://github.com/opengeos/GeoLibre/blob/main/sedona-workspace.ts). Exceeding this requires the Python side-car.

### How does GeoLibre detect which engine to use?

The `runSedonaQuery` function probes the `/sql/status` endpoint and caches the result for 5 seconds (`SIDECAR_PROBE_TTL_MS`). If the side-car responds, queries route to Python; otherwise, they execute in the browser via WebAssembly.

### Can I run spatial queries without installing Python?

Yes. The CereusDB WebAssembly engine runs entirely in the browser without external dependencies, provided your data stays below the 50,000 feature limit per layer.

### Where is the WebAssembly bundle loaded from?

The `cereus.wasm` file is bundled with the application build and fetched relative to the base URL when `loadCereusDb()` is first called in [`sedona-workspace.ts`](https://github.com/opengeos/GeoLibre/blob/main/sedona-workspace.ts).