.md

dcupl vs alternatives

Understanding how dcupl compares to other data solutions helps you choose the right tool for your project. This guide compares dcupl with popular alternatives across different categories.

Quick comparison table

Feature dcupl Firebase Supabase TanStack Query Redux Elasticsearch/Algolia
Primary Focus Client-side querying Real-time database Backend-as-a-Service Server state caching Global state management Full-text search
Query Execution Client-side, or on a server-hosted REST API (RAPI) instance Server-side Server-side Server-side Client-side (local) Server-side
Real-time Sync Manual refresh Built-in Built-in Polling/WebSocket Manual Near real-time
Dataset Size Limited by memory; larger data on a REST API instance Unlimited Unlimited Unlimited Limited by memory Unlimited
Offline Support Full (after load) Partial Limited Cache only Full None
Self-Hosted SDK: Yes No Yes N/A N/A Elasticsearch: Yes
Learning Curve Low Medium Medium Low High Medium-High
Cost Free SDK and CLI on npm, Console optional Usage-based Usage-based Free Free Usage-based

Understanding the categories

Before diving into detailed comparisons, it helps to understand what category each tool falls into:

flowchart TB
  subgraph backend["Backend Services"]
    FIREBASE["Firebase<br/>Real-time Database"]
    SUPABASE["Supabase<br/>Postgres Backend"]
    SEARCH["Elasticsearch/Algolia<br/>Search Services"]
  end

  subgraph frontend["Frontend Libraries"]
    DCUPL["dcupl<br/>Client-side Query Engine"]
    TANSTACK["TanStack Query<br/>Server State Cache"]
    REDUX["Redux<br/>State Management"]
  end

  APP[Your Application]

  backend --> APP
  frontend --> APP

dcupl is unique because it brings query capabilities typically found in backend services to the client side.

dcupl vs Firebase

Firebase is Google's Backend-as-a-Service platform with real-time database capabilities.

Key differences

Aspect dcupl Firebase
Architecture Data loaded to client, queries run locally Data stays on server, queries run remotely
Query Latency Instant (no network) Network dependent
Complex Queries Full query language Limited query operators
Faceted Search Built-in Requires workarounds
Cost Model No per-query costs Charged per read/write

When to choose Firebase

  • You need real-time multi-user synchronization (collaborative editing, chat)
  • Your data changes frequently and must be instantly reflected across clients
  • You need user authentication built into your data layer
  • Your dataset is too large to load into client memory — or keep dcupl and run the same models on a server-hosted REST API instance

When to choose dcupl

  • You need instant filter and search without network latency
  • Your data is read-heavy with infrequent updates
  • You want to reduce server costs by offloading computation to clients
  • You need complex faceted search like product catalogs

Code comparison

dcupl-query.ts
// dcupl: Query runs instantly in browser
const list = dcupl.lists.create({ modelKey: 'Product' });

list.catalog.query.addCondition([
  { attribute: 'category', operator: 'eq', value: 'Electronics' },
  { attribute: 'price', operator: 'lte', value: 500 },
]);

// Instant results, no network request
const results = list.catalog.query.items();
const facets = list.catalog.fn.facets({ attribute: 'brand' });
firebase-query.ts
// Firebase: Each query hits the server
const q = query(collection(db, 'products'), where('category', '==', 'Electronics'), where('price', '<=', 500));

// Network request required
const snapshot = await getDocs(q);
// Facets require separate queries or Cloud Functions

dcupl vs Supabase

Supabase is a Firebase alternative built on PostgreSQL.

Key differences

Aspect dcupl Supabase
Database In-memory (client, or a server-hosted REST API instance) PostgreSQL (server)
Query Language dcupl operators SQL / PostgREST
Aggregations Client-side Server-side SQL
Row-Level Security None in the client: every loaded item is readable by the user Built-in policies
Full-Text Search None: regex/substring find and prefix fn.suggest, no ranking PostgreSQL FTS

When to choose Supabase

  • You need a full backend with authentication, storage, and edge functions
  • You prefer SQL and relational data modeling
  • You need row-level security policies
  • Your application requires write-heavy operations

When to choose dcupl

  • Your team (or your agent) needs to work on real data before a backend exists
  • You want instant client-side filtering without API round-trips
  • You're building a read-heavy application like a catalog or dashboard
  • You need SSR-compatible data that works the same on server and client

Architecture comparison

flowchart LR
  subgraph supabase["Supabase Architecture"]
    direction LR
    S_APP[App] --> S_API[PostgREST API]
    S_API --> S_DB[(PostgreSQL)]
  end
flowchart LR
  subgraph dcupl["dcupl Architecture"]
    direction LR
    D_DATA[Data Source] --> D_SDK[dcupl SDK]
    D_SDK --> D_APP[App]
  end

With Supabase, every query goes to the server. With dcupl, data loads once, then all queries are instant.

dcupl vs TanStack Query

TanStack Query (formerly React Query) is a server state management library for fetching, caching, and updating data.

Key differences

Aspect dcupl TanStack Query
Purpose Query engine with data Server state cache
Data Location Loaded into SDK Cached from server
Querying Full query language Depends on your API
Filtering Built-in operators You implement it
Framework Any framework React, Vue, Svelte, etc.

When to choose TanStack Query

  • You already have well-designed APIs with filtering and pagination
  • You need to cache and synchronize server state
  • Your data is too large to load entirely to the client — or keep dcupl and run the same models on a server-hosted REST API instance
  • You need real-time updates via WebSocket subscriptions

When to choose dcupl

  • You want built-in filtering, sorting, and faceting without building APIs
  • Your dataset fits in memory and benefits from instant local queries
  • You're building a product finder, data table, or catalog interface
  • You want to prototype quickly without backend work

Complementary usage

dcupl and TanStack Query can work together:

tanstack-with-dcupl.ts
// A sketch for a React component. `dcupl` is your app's instance: the Product model
// is set and `await dcupl.init()` has run once. fetchProducts is your API call.
const { data } = useQuery({
  queryKey: ['products'],
  queryFn: fetchProducts,
});

// Whenever TanStack Query delivers data, replace the products in dcupl
useEffect(() => {
  if (!data) return;
  dcupl.data.set(data, { model: 'Product' }); // staged
  dcupl.update().then((ok) => {
    // update() resolves false instead of throwing
    if (!ok) console.error('dcupl.update() failed');
  });
}, [data]);

// TanStack Query: fetching & caching
// dcupl: filtering & faceting (lists show the new data on their next query)

dcupl vs Redux

Redux is a predictable state container for JavaScript applications.

Key differences

Aspect dcupl Redux
Purpose Data querying State management
Data Structure Models with types Any shape
Querying Built-in query language Manual selectors
Filtering Operators, facets You implement it
Boilerplate Minimal Historically high

When to choose Redux

  • You need complex application state beyond data (UI state, user preferences)
  • You want time-travel debugging and state inspection
  • Your team is already proficient with Redux patterns
  • You need fine-grained control over state updates

When to choose dcupl

  • Your state is primarily data that needs filtering and aggregation
  • You want built-in query capabilities without writing reducers
  • You're building a data-driven UI (catalogs, tables, dashboards)
  • You prefer less boilerplate for data operations

Code comparison

dcupl-filtering.ts
// dcupl: Filtering is built-in
const list = dcupl.lists.create({ modelKey: 'Product' });

list.catalog.query.addCondition([{ attribute: 'inStock', operator: 'eq', value: true }]);

// Get filtered items and facets
const items = list.catalog.query.items();
const brands = list.catalog.fn.facets({ attribute: 'brand' });
redux-filtering.ts
// Redux: You implement filtering logic
const selectFilteredProducts = createSelector([selectProducts, selectFilters], (products, filters) => {
  return products.filter((p) => {
    if (filters.inStock && !p.inStock) return false;
    // ... more filter logic
    return true;
  });
});

// Facets require additional selectors
const selectBrandCounts = createSelector([selectFilteredProducts], (products) => {
  // Count by brand manually
});

dcupl vs Elasticsearch / Algolia

Elasticsearch and Algolia are search-as-a-service platforms optimized for full-text search.

Key differences

Aspect dcupl Elasticsearch/Algolia
Search Type Structured + text Optimized for text
Infrastructure None for the SDK (optional server-hosted REST API instance) Server cluster
Latency Instant (local); a REST API instance adds a network round trip Network round trip
Typo Tolerance None Advanced
Relevance Tuning None (no relevance ranking) Configurable ranking
Cost Free SDK Algolia: per search request and record; Elastic Cloud: by resources or usage

When to choose Elasticsearch/Algolia

  • You need advanced full-text search with typo tolerance and synonyms
  • Your dataset is too large to ship to the client — or keep dcupl and run the same models on a server-hosted REST API instance
  • You need relevance ranking and machine learning features
  • Search is a core differentiator for your product

When to choose dcupl

  • You need structured filtering more than fuzzy text search
  • Your dataset fits in memory. Measured with 1 million items: indexed queries took 25–65 ms, facets about 2.7 s
  • You want zero search infrastructure to manage
  • You need instant results without any network latency
  • You want to avoid per-search costs

Hybrid approach

Use both for the best of both worlds:

flowchart LR
  USER[User] --> UI[Search UI]
  UI --> |"Full-text search"| ALGOLIA[Algolia]
  ALGOLIA --> |"Return IDs"| UI
  UI --> |"Filter by IDs"| DCUPL[dcupl SDK]
  DCUPL --> |"Facets & details"| UI
hybrid-search.ts
// Use Algolia for text search, dcupl for filtering
const searchResults = await algoliaIndex.search(query);
const matchingIds = searchResults.hits.map((h) => h.objectID);

// Filter dcupl data to matching IDs
list.catalog.query.addCondition([{ attribute: 'key', operator: 'in', value: matchingIds }]);

// dcupl provides facets for the search results
const facets = list.catalog.fn.facets({ attribute: 'category' });

Decision framework

Use this flowchart to help decide:

flowchart TD
  START[What do you need?] --> Q1{Real-time<br/>multi-user sync?}
  Q1 --> |Yes| FIREBASE[Firebase/Supabase]
  Q1 --> |No| Q2{Full-text search<br/>with typo tolerance?}
  Q2 --> |Yes| SEARCH["Elasticsearch/Algolia<br/>(+ dcupl for facets, see Hybrid Approach)"]
  Q2 --> |No| Q4{Dataset fits<br/>in memory?}
  Q4 --> |Yes| Q5{Need filtering,<br/>facets, aggregations?}
  Q5 --> |Yes| DCUPL[dcupl]
  Q5 --> |No| TANSTACK[TanStack Query]
  Q4 --> |No| Q6{Need SQL?}
  Q6 --> |Yes| SUPABASE[Supabase]
  Q6 --> |No| RAPI["dcupl REST API instance<br/>(server-hosted, same models)"]

Summary

Solution Best For
dcupl Read-heavy apps needing instant client-side filtering, facets, and aggregations; data too large for the client runs on a server-hosted REST API instance
Firebase Real-time collaborative apps with multi-user sync
Supabase Full-stack apps needing a SQL backend with auth and storage
TanStack Query Apps with existing APIs that need efficient server state caching
Redux Complex apps needing predictable state beyond just data
Elasticsearch/Algolia Large-scale full-text search with advanced relevance features

dcupl shines when you need instant, client-side data exploration for datasets that fit in the browser's memory. It eliminates network latency for queries, reduces server costs, and provides built-in filtering and faceting that would otherwise require significant backend work. Larger data runs on a server-hosted REST API instance that answers the same dcupl queries over HTTP.