Tool-pair integration pattern
Tally + Supabase integration (form responses)
Tally + Supabase is the pattern for capturing form data into your application database. Tally hosts the form; Supabase stores the responses. The bridge is a Tally webhook that fires on submission and writes a row to Supabase.
Verified · editorial policy
Tally owns (teardown →)
Form UI, conditional logic, file uploads, response storage (as a backup), conditional emails, embed widgets.
Supabase owns
Long-term response storage, querying + reporting, integration with the rest of the application's data model, row-level security on responses.
Integration shape
Webhook to Supabase. Tally fires a JSON payload on every submission; your endpoint receives it, validates, and inserts a row into a Supabase responses table.
Implementation steps
Step 1
Design the Supabase responses table
Columns: id, form_id, submitted_at, response_data (JSONB), user_id (if authenticated submission), source. Use JSONB for response_data to preserve schema flexibility.
Gotcha: Flattening Tally responses into normalized columns ties your schema to the form structure. If form fields change, the schema breaks. Keep JSONB.
Step 2
Add a Tally webhook to your Supabase project
In Tally form settings, add a webhook pointing to your Next.js Route Handler. Tally signs the webhook payload; verify the signature server-side.
Gotcha: Tally's webhook signature mechanism is documented; do not skip verification. Webhook endpoints without verification can be spammed by anyone.
Step 3
Build the Route Handler that receives Tally webhooks
Next.js Route Handler at /api/tally-webhook. Verify signature, parse payload, insert row to Supabase responses table.
Gotcha: Idempotency: Tally retries failed webhooks. Use the Tally submission ID as the idempotency key.
Step 4
Handle authenticated vs anonymous submissions
If your form is for logged-in users, pass the user_id in the URL or hidden field. The webhook handler reads it and associates the response with the user in Supabase.
Gotcha: Anonymous form submissions with no user context can lose context. Always include at least an email or session ID for traceability.
Step 5
Test the full pipeline
Submit a real test response via the live Tally form. Confirm webhook fires, Supabase row appears, signature verification passes.
Gotcha: Skipping this means the first production submission silently fails. Test before launching.
Common gotchas across the whole integration
- Tally's free tier limits monthly submissions; if you scale forms, check the plan ceiling before launching.
- Webhook latency means there's a 1-3 second gap between form submission and Supabase row. Plan downstream logic to tolerate this.
- Email notifications can come from Tally OR from Supabase trigger. Pick one to avoid duplicate notifications.
- Tally allows file uploads; the webhook payload includes URLs to files hosted by Tally, not the files themselves. Long-term storage requires you to download to your own storage.
When NOT to build this integration
If you need real-time form validation against your own database (e.g., 'is this email already a customer?'), Tally's hosted form is too constrained. Build the form natively in Next.js + Supabase for that case.
Frequently asked
- Can I use Tally's response storage instead of Supabase?
- For low-volume forms (under 100/month) where you do not need to integrate with the rest of your app's data — yes. Tally's response storage is fine for standalone surveys. Once responses need to inform application behavior, route to Supabase.
Other tool-pair integrations
See the stack this integration belongs to
Integration patterns assume the right stack underneath. Use the stack recommendations to pick the right tools first, then the integration to wire them together.