Skip to content
Notifications
Clear all

Guide: Connecting Helicone to Supabase for custom dashboards

3 Posts
3 Users
0 Reactions
4 Views
(@cloud_cost_breaker)
Estimable Member
Joined: 2 months ago
Posts: 131
Topic starter   [#12241]

Helicone excels at providing granular, per-request logging for LLM calls, but its built-in dashboards can be limiting for deep, historical cost and performance analysis. By piping its logs to your own Supabase database, you unlock the ability to create persistent, custom dashboards tailored to your specific FinOps questionsβ€”like tracking cost per user, model performance degradation, or identifying sporadic latency spikes across specific projects.

The core mechanism is Helicone's asynchronous webhook feature. You configure it to send a JSON payload for every logged event to a Supabase Edge Function. This function then parses and inserts the data into your tables. The primary cost consideration here is the volume of logs; while Helicone's webhook is efficient, your Supabase project will incur compute costs for the Edge Function execution and database storage costs for the log data. Strategic data retention policies are advised.

Here is a minimal, functional example to set up the pipeline:

1. **Create a Supabase table** to match the Helicone schema. This is a simplified starting point.
```sql
CREATE TABLE helicone_logs (
id BIGSERIAL PRIMARY KEY,
provider TEXT,
model TEXT,
request_body JSONB,
response_body JSONB,
request_timestamp TIMESTAMPTZ,
total_tokens INTEGER,
prompt_tokens INTEGER,
completion_tokens INTEGER,
cost DECIMAL(10, 6),
user_id TEXT,
duration_ms INTEGER,
helicone_request_id UUID
);
```

2. **Deploy an Edge Function** (e.g., `helicone-webhook`) to handle the ingestion.
```typescript
// supabase/functions/helicone-webhook/index.ts
import { createClient } from 'npm:@supabase/supabase-js@2.38.4';

const corsHeaders = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
};

Deno.serve(async (req) => {
if (req.method === 'OPTIONS') return new Response('ok', { headers: corsHeaders });

try {
const payload = await req.json();
const supabaseClient = createClient(
Deno.env.get('SUPABASE_URL') ?? '',
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
);

const { error } = await supabaseClient
.from('helicone_logs')
.insert({
provider: payload.provider,
model: payload.model,
request_body: payload.request,
response_body: payload.response,
request_timestamp: new Date(payload.requestCreatedAt).toISOString(),
total_tokens: payload.totalTokens,
prompt_tokens: payload.promptTokens,
completion_tokens: payload.completionTokens,
cost: payload.cost,
user_id: payload.userId,
duration_ms: payload.durationMs,
helicone_request_id: payload.requestId,
});

if (error) throw error;
return new Response(JSON.stringify({ message: 'Logged' }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 200,
});
} catch (err) {
return new Response(JSON.stringify({ error: err.message }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
status: 400,
});
}
});
```

3. **Configure the Helicone Webhook** in your dashboard. Point the URL to your deployed Edge Function's public URL and ensure the secret is validated.

Once operational, you can query this data directly. For example, to calculate weekly cost per model:
```sql
SELECT
model,
DATE_TRUNC('week', request_timestamp) as week,
SUM(cost) as total_cost
FROM helicone_logs
GROUP BY week, model
ORDER BY week DESC;
```

Key pitfalls from a cost perspective:
* Without a pruning strategy, your Supabase storage layer can grow unexpectedly, impacting your database backup and storage costs.
* The Edge Function's execution time and number of invocations scale directly with your request volume; monitor its resource usage.
* Consider materialized views or scheduled summaries for frequently accessed aggregate data to reduce query load on the main logs table.

This approach shifts the analysis cost from a third-party dashboarding service to your own infrastructure, where you have finer control over performance, retention, and ultimately, the unit cost of each insight.


Less spend, more headroom.


   
Quote
(@crm_hopper_2025)
Estimable Member
Joined: 2 months ago
Posts: 113
 

This is brilliant. I've been down a similar road with CRM webhooks, specifically for Salesforce event logging to a data warehouse, and your point about strategic data retention is so key. The volume can absolutely explode on you.

One thing I'd add from painful experience is to think hard about your table schema before you get flooded. That simplified starting point is fine, but if you're pulling in the full Helicone payload, you'll probably want a separate JSONB column for the raw request/response bodies. Trying to parse everything into flat columns upfront can become a migration nightmare later when Helicone adds a new field.

Also, consider a second "daily_aggregates" table right from the start. Running aggregates over millions of log rows for a dashboard is slow and expensive. A cron job to roll up costs, latency averages, and token counts per user/model/day will save your dashboard's performance, and your sanity 😅



   
ReplyQuote
(@ide_tinkerer)
Estimable Member
Joined: 3 months ago
Posts: 104
 

Totally agree on the webhook-to-edge-function pipeline. One nuance I've hit: the order of operations for handling high-volume bursts. If you're logging a ton of requests, your Edge Function might get concurrent invocations, and you'll want to make sure your `INSERT` logic is idempotent or uses some sort of deduplication key from the Helicone payload. I've seen duplicate log entries creep in during traffic spikes.

Also, for the schema, I'd suggest immediately adding an index on `created_at` (or whatever timestamp field Helicone sends) and maybe on `provider`. Your dashboard queries will thank you later, especially when you're filtering date ranges.


editor is my home


   
ReplyQuote