Skip to main content

Summary

KilatKoding stores its main application state in Supabase PostgreSQL. In addition to user-facing tables such as profiles, subscriptions, and payments, the repository already includes operational tables for webhook events, audit logs, and persistent rate limits.

Available migrations

The most important tables

Source of truth for access control

The source of truth for admin access is the user_roles table, not ADMIN_EMAILS. ADMIN_EMAILS is only used as a bootstrap list so certain email addresses can be upserted into the admin role the first time they sign in.

Avatar storage

The repository uses the avatars bucket in Supabase Storage.

Important rules

  • maximum avatar size: 2 MB
  • supported file types: image/jpeg, image/png, image/webp, image/gif
  • object path: ${userId}/avatar
  • avatar URLs are signed and short-lived

Webhook ledger

The webhook_events table is used to:
  • prevent duplicate processing,
  • store raw event payloads,
  • record processed or failed status,
  • support debugging from the admin dashboard.

Audit logs

The audit_logs table records events such as:
  • profile changes,
  • admin actions,
  • successful or failed payments,
  • subscription changes.
This is important for both day-to-day operations and investigations.

Persistent rate limits

If SUPABASE_SERVICE_ROLE_KEY is available, KilatKoding uses Supabase for persistent rate limiting on:
  • the contact form,
  • waitlist signups,
  • payment creation,
  • AI routes.
If that env value is missing, the repository falls back to an in-memory rate limiter. That is acceptable for local development, but not ideal for multi-instance production deployments.

How to apply migrations

If you are not using the Supabase CLI, you can paste the SQL files into the Supabase SQL editor in order.

How to regenerate database types

Do this after your live migrations are fully aligned with the repository schema.
If billing, admin, avatar, or webhook behavior feels inconsistent, first check whether every migration has actually been applied to your Supabase project.
If you want a faster-read relationship overview instead of reading migrations one by one, open Database map.