Home

Self-Hosting Analytics

The Supabase Analytics server is a Logflare self-hostable instance that manages the ingestion and query pipelines for searching and aggregating structured analytics events.

When self-hosting the Analytics server, the full logging experience matching that of the Supabase Platform is available in the Studio instance, allowing for an integrated and enhanced development experience. However, it's important to note that certain differences may arise due to the platform's infrastructure.

Logflare Technical Docs

All logflare technical docs are available at https://docs.logflare.app

Getting Started#

Using the example self-hosting stack based on docker-compose, you include the logging related services using the following command

1# assuming you clone the supabase/supabase repo.
2cd docker
3docker compose -f docker-compose.yml -f docker-compose-logging.yml up

This would include two additional docker services to your compose stack: Logflare and Vector.

Self-hosting

Read more about self-hosting Logflare as your analytics server.

Differences#

API logs rely on Kong instead of the Supabase Cloud API Gateway. Logs from Kong are not enriched with platform-only data.

Within the self-hosted setup, all logs are routed to Logflare via Vector. As Kong routes API requests to PostgREST, self-hosted or local deployments will result in Kong request logs instead. This would result in differences in the log event metadata between self-hosted API requests and Supabase Platform requests.

BigQuery#

All log event data is stored in and queried from BigQuery. To use the Analytics server with Supabase you'll need a Google Cloud Platform account for access to BigQuery.

Make sure to set the GOOGLE_DATASET_ID_APPEND, GOOGLE_PROJECT_ID and GOOGLE_PROJECT_NUMBER environment variables.

Download your Google Cloud API JWT and store it under gcloud.json in your working directory.

note

You must also enable billing on your Google Cloud project, as the streaming inserts feature is required.

Production Recommendations#

To self-host in a production setting, we recommend performing the following for a better experience.

Ensure that Logflare is behind a firewall and restrict all network access to it besides safe requests.#

Self-hosted Logflare has UI authentication disabled and is intended for exposure to the internet. We recommend restricting access to the dashboard, accessible at the /dashboard path. If dashboard access is required for managing sources, we recommend having an authentication layer, such as a VPN.

Use a different Postgres Database to store Logflare data.#

Logflare requires a Postgres database to function. However, if there is an issue with you self-hosted Postgres service, you would not be able to debug it as it would also bring Logflare down together.

The self-hosted example is only used as a minimal example on running the entire stack, however it is not recommended to use the same database server for both production and observability.

List endpoints

get/api/endpoints

Responses

Endpoint List Response

1{
2  "schema": {
3    "items": {
4      "properties": {
5        "cache_duration_seconds": {
6          "type": "integer"
7        },
8        "enable_auth": {
9          "type": "boolean"
10        },
11        "inserted_at": {
12          "format": "date-time",
13          "type": "string"
14        },
15        "max_limit": {
16          "type": "integer"
17        },
18        "name": {
19          "type": "string"
20        },
21        "proactive_requerying_seconds": {
22          "type": "integer"
23        },
24        "query": {
25          "type": "string"
26        },
27        "sandboxable": {
28          "type": "boolean"
29        },
30        "source_mapping": {
31          "type": "object"
32        },
33        "token": {
34          "type": "string"
35        },
36        "updated_at": {
37          "format": "date-time",
38          "type": "string"
39        }
40      },
41      "required": [
42        "name",
43        "query"
44      ],
45      "title": "Endpoint",
46      "type": "object"
47    },
48    "type": "array"
49  }
50}

Create endpoint

post/api/endpoints

Responses

Created Response

1{
2  "schema": {
3    "properties": {
4      "cache_duration_seconds": {
5        "type": "integer"
6      },
7      "enable_auth": {
8        "type": "boolean"
9      },
10      "inserted_at": {
11        "format": "date-time",
12        "type": "string"
13      },
14      "max_limit": {
15        "type": "integer"
16      },
17      "name": {
18        "type": "string"
19      },
20      "proactive_requerying_seconds": {
21        "type": "integer"
22      },
23      "query": {
24        "type": "string"
25      },
26      "sandboxable": {
27        "type": "boolean"
28      },
29      "source_mapping": {
30        "type": "object"
31      },
32      "token": {
33        "type": "string"
34      },
35      "updated_at": {
36        "format": "date-time",
37        "type": "string"
38      }
39    },
40    "required": [
41      "name",
42      "query"
43    ],
44    "title": "Endpoint",
45    "type": "object"
46  }
47}

Delete endpoint

delete/api/endpoints/{token}

Path Parameters
  • token
    REQUIRED
    no type

    Endpoint Token

Responses

Accepted Response

Fetch endpoint

get/api/endpoints/{token}

Path Parameters
  • token
    REQUIRED
    no type

    Endpoint Token

Responses

Endpoint Response

1{
2  "schema": {
3    "properties": {
4      "cache_duration_seconds": {
5        "type": "integer"
6      },
7      "enable_auth": {
8        "type": "boolean"
9      },
10      "inserted_at": {
11        "format": "date-time",
12        "type": "string"
13      },
14      "max_limit": {
15        "type": "integer"
16      },
17      "name": {
18        "type": "string"
19      },
20      "proactive_requerying_seconds": {
21        "type": "integer"
22      },
23      "query": {
24        "type": "string"
25      },
26      "sandboxable": {
27        "type": "boolean"
28      },
29      "source_mapping": {
30        "type": "object"
31      },
32      "token": {
33        "type": "string"
34      },
35      "updated_at": {
36        "format": "date-time",
37        "type": "string"
38      }
39    },
40    "required": [
41      "name",
42      "query"
43    ],
44    "title": "Endpoint",
45    "type": "object"
46  }
47}

Update endpoint

patch/api/endpoints/{token}

Path Parameters
  • token
    REQUIRED
    no type

    Endpoint Token

Responses

Created Response

1{
2  "schema": {
3    "properties": {
4      "cache_duration_seconds": {
5        "type": "integer"
6      },
7      "enable_auth": {
8        "type": "boolean"
9      },
10      "inserted_at": {
11        "format": "date-time",
12        "type": "string"
13      },
14      "max_limit": {
15        "type": "integer"
16      },
17      "name": {
18        "type": "string"
19      },
20      "proactive_requerying_seconds": {
21        "type": "integer"
22      },
23      "query": {
24        "type": "string"
25      },
26      "sandboxable": {
27        "type": "boolean"
28      },
29      "source_mapping": {
30        "type": "object"
31      },
32      "token": {
33        "type": "string"
34      },
35      "updated_at": {
36        "format": "date-time",
37        "type": "string"
38      }
39    },
40    "required": [
41      "name",
42      "query"
43    ],
44    "title": "Endpoint",
45    "type": "object"
46  }
47}

List sources

get/api/sources

Responses

Source List Response

1{
2  "schema": {
3    "items": {
4      "properties": {
5        "api_quota": {
6          "type": "integer"
7        },
8        "bigquery_table_ttl": {
9          "type": "integer"
10        },
11        "bq_table_id": {
12          "type": "string"
13        },
14        "bq_table_schema": {
15          "type": "object"
16        },
17        "custom_event_message_keys": {
18          "type": "string"
19        },
20        "favorite": {
21          "type": "boolean"
22        },
23        "has_rejected_events": {
24          "type": "boolean"
25        },
26        "id": {},
27        "inserted_at": {
28          "format": "date-time",
29          "type": "string"
30        },
31        "metrics": {
32          "type": "object"
33        },
34        "name": {
35          "type": "string"
36        },
37        "notifications": {
38          "items": {
39            "properties": {
40              "other_email_notifications": {
41                "type": "string"
42              },
43              "team_user_ids_for_email": {
44                "allOf": {
45                  "type": "string"
46                },
47                "type": "array"
48              },
49              "team_user_ids_for_schema_updates": {
50                "allOf": {
51                  "type": "string"
52                },
53                "type": "array"
54              },
55              "team_user_ids_for_sms": {
56                "allOf": {
57                  "type": "string"
58                },
59                "type": "array"
60              },
61              "user_email_notifications": {
62                "type": "boolean"
63              },
64              "user_schema_update_notifications": {
65                "type": "boolean"
66              },
67              "user_text_notifications": {
68                "type": "boolean"
69              }
70            },
71            "title": "Notification",
72            "type": "object"
73          },
74          "type": "array"
75        },
76        "public_token": {
77          "type": "string"
78        },
79        "slack_hook_url": {
80          "type": "string"
81        },
82        "token": {
83          "type": "string"
84        },
85        "updated_at": {
86          "format": "date-time",
87          "type": "string"
88        },
89        "webhook_notification_url": {
90          "type": "string"
91        }
92      },
93      "required": [
94        "name"
95      ],
96      "title": "Source",
97      "type": "object"
98    },
99    "type": "array"
100  }
101}

Create source

post/api/sources

Responses

Created Response

1{
2  "schema": {
3    "properties": {
4      "api_quota": {
5        "type": "integer"
6      },
7      "bigquery_table_ttl": {
8        "type": "integer"
9      },
10      "bq_table_id": {
11        "type": "string"
12      },
13      "bq_table_schema": {
14        "type": "object"
15      },
16      "custom_event_message_keys": {
17        "type": "string"
18      },
19      "favorite": {
20        "type": "boolean"
21      },
22      "has_rejected_events": {
23        "type": "boolean"
24      },
25      "id": {},
26      "inserted_at": {
27        "format": "date-time",
28        "type": "string"
29      },
30      "metrics": {
31        "type": "object"
32      },
33      "name": {
34        "type": "string"
35      },
36      "notifications": {
37        "items": {
38          "properties": {
39            "other_email_notifications": {
40              "type": "string"
41            },
42            "team_user_ids_for_email": {
43              "allOf": {
44                "type": "string"
45              },
46              "type": "array"
47            },
48            "team_user_ids_for_schema_updates": {
49              "allOf": {
50                "type": "string"
51              },
52              "type": "array"
53            },
54            "team_user_ids_for_sms": {
55              "allOf": {
56                "type": "string"
57              },
58              "type": "array"
59            },
60            "user_email_notifications": {
61              "type": "boolean"
62            },
63            "user_schema_update_notifications": {
64              "type": "boolean"
65            },
66            "user_text_notifications": {
67              "type": "boolean"
68            }
69          },
70          "title": "Notification",
71          "type": "object"
72        },
73        "type": "array"
74      },
75      "public_token": {
76        "type": "string"
77      },
78      "slack_hook_url": {
79        "type": "string"
80      },
81      "token": {
82        "type": "string"
83      },
84      "updated_at": {
85        "format": "date-time",
86        "type": "string"
87      },
88      "webhook_notification_url": {
89        "type": "string"
90      }
91    },
92    "required": [
93      "name"
94    ],
95    "title": "Source",
96    "type": "object"
97  }
98}

Delete source

delete/api/sources/{token}

Path Parameters
  • token
    REQUIRED
    no type

    Source Token

Responses

Accepted Response

Fetch source

get/api/sources/{token}

Path Parameters
  • token
    REQUIRED
    no type

    Source Token

Responses

Source Response

1{
2  "schema": {
3    "properties": {
4      "api_quota": {
5        "type": "integer"
6      },
7      "bigquery_table_ttl": {
8        "type": "integer"
9      },
10      "bq_table_id": {
11        "type": "string"
12      },
13      "bq_table_schema": {
14        "type": "object"
15      },
16      "custom_event_message_keys": {
17        "type": "string"
18      },
19      "favorite": {
20        "type": "boolean"
21      },
22      "has_rejected_events": {
23        "type": "boolean"
24      },
25      "id": {},
26      "inserted_at": {
27        "format": "date-time",
28        "type": "string"
29      },
30      "metrics": {
31        "type": "object"
32      },
33      "name": {
34        "type": "string"
35      },
36      "notifications": {
37        "items": {
38          "properties": {
39            "other_email_notifications": {
40              "type": "string"
41            },
42            "team_user_ids_for_email": {
43              "allOf": {
44                "type": "string"
45              },
46              "type": "array"
47            },
48            "team_user_ids_for_schema_updates": {
49              "allOf": {
50                "type": "string"
51              },
52              "type": "array"
53            },
54            "team_user_ids_for_sms": {
55              "allOf": {
56                "type": "string"
57              },
58              "type": "array"
59            },
60            "user_email_notifications": {
61              "type": "boolean"
62            },
63            "user_schema_update_notifications": {
64              "type": "boolean"
65            },
66            "user_text_notifications": {
67              "type": "boolean"
68            }
69          },
70          "title": "Notification",
71          "type": "object"
72        },
73        "type": "array"
74      },
75      "public_token": {
76        "type": "string"
77      },
78      "slack_hook_url": {
79        "type": "string"
80      },
81      "token": {
82        "type": "string"
83      },
84      "updated_at": {
85        "format": "date-time",
86        "type": "string"
87      },
88      "webhook_notification_url": {
89        "type": "string"
90      }
91    },
92    "required": [
93      "name"
94    ],
95    "title": "Source",
96    "type": "object"
97  }
98}

Update source

patch/api/sources/{token}

Path Parameters
  • token
    REQUIRED
    no type

    Source Token

Responses

Created Response

1{
2  "schema": {
3    "properties": {
4      "api_quota": {
5        "type": "integer"
6      },
7      "bigquery_table_ttl": {
8        "type": "integer"
9      },
10      "bq_table_id": {
11        "type": "string"
12      },
13      "bq_table_schema": {
14        "type": "object"
15      },
16      "custom_event_message_keys": {
17        "type": "string"
18      },
19      "favorite": {
20        "type": "boolean"
21      },
22      "has_rejected_events": {
23        "type": "boolean"
24      },
25      "id": {},
26      "inserted_at": {
27        "format": "date-time",
28        "type": "string"
29      },
30      "metrics": {
31        "type": "object"
32      },
33      "name": {
34        "type": "string"
35      },
36      "notifications": {
37        "items": {
38          "properties": {
39            "other_email_notifications": {
40              "type": "string"
41            },
42            "team_user_ids_for_email": {
43              "allOf": {
44                "type": "string"
45              },
46              "type": "array"
47            },
48            "team_user_ids_for_schema_updates": {
49              "allOf": {
50                "type": "string"
51              },
52              "type": "array"
53            },
54            "team_user_ids_for_sms": {
55              "allOf": {
56                "type": "string"
57              },
58              "type": "array"
59            },
60            "user_email_notifications": {
61              "type": "boolean"
62            },
63            "user_schema_update_notifications": {
64              "type": "boolean"
65            },
66            "user_text_notifications": {
67              "type": "boolean"
68            }
69          },
70          "title": "Notification",
71          "type": "object"
72        },
73        "type": "array"
74      },
75      "public_token": {
76        "type": "string"
77      },
78      "slack_hook_url": {
79        "type": "string"
80      },
81      "token": {
82        "type": "string"
83      },
84      "updated_at": {
85        "format": "date-time",
86        "type": "string"
87      },
88      "webhook_notification_url": {
89        "type": "string"
90      }
91    },
92    "required": [
93      "name"
94    ],
95    "title": "Source",
96    "type": "object"
97  }
98}

List teams

get/api/teams

Responses

Team List Response

1{
2  "schema": {
3    "items": {
4      "properties": {
5        "name": {
6          "type": "string"
7        },
8        "team_users": {
9          "items": {
10            "properties": {
11              "email": {
12                "type": "string"
13              },
14              "name": {
15                "type": "string"
16              }
17            },
18            "required": [
19              "email",
20              "name"
21            ],
22            "title": "TeamUser",
23            "type": "object"
24          },
25          "type": "array"
26        },
27        "token": {
28          "type": "string"
29        },
30        "user": {
31          "properties": {
32            "api_key": {
33              "type": "string"
34            },
35            "api_quota": {
36              "type": "integer"
37            },
38            "bigquery_dataset_id": {
39              "type": "string"
40            },
41            "bigquery_dataset_location": {
42              "type": "string"
43            },
44            "bigquery_project_id": {
45              "type": "string"
46            },
47            "company": {
48              "type": "string"
49            },
50            "email": {
51              "type": "string"
52            },
53            "email_me_product": {
54              "type": "boolean"
55            },
56            "email_preferred": {
57              "type": "string"
58            },
59            "image": {
60              "type": "string"
61            },
62            "name": {
63              "type": "string"
64            },
65            "phone": {
66              "type": "string"
67            },
68            "provider": {
69              "type": "string"
70            },
71            "token": {
72              "type": "string"
73            }
74          },
75          "required": [
76            "email",
77            "provider",
78            "token",
79            "provider_uid",
80            "api_key"
81          ],
82          "title": "User",
83          "type": "object"
84        }
85      },
86      "required": [
87        "name"
88      ],
89      "title": "Team",
90      "type": "object"
91    },
92    "type": "array"
93  }
94}

Create Team

post/api/teams

Responses

Created Response

1{
2  "schema": {
3    "properties": {
4      "name": {
5        "type": "string"
6      },
7      "team_users": {
8        "items": {
9          "properties": {
10            "email": {
11              "type": "string"
12            },
13            "name": {
14              "type": "string"
15            }
16          },
17          "required": [
18            "email",
19            "name"
20          ],
21          "title": "TeamUser",
22          "type": "object"
23        },
24        "type": "array"
25      },
26      "token": {
27        "type": "string"
28      },
29      "user": {
30        "properties": {
31          "api_key": {
32            "type": "string"
33          },
34          "api_quota": {
35            "type": "integer"
36          },
37          "bigquery_dataset_id": {
38            "type": "string"
39          },
40          "bigquery_dataset_location": {
41            "type": "string"
42          },
43          "bigquery_project_id": {
44            "type": "string"
45          },
46          "company": {
47            "type": "string"
48          },
49          "email": {
50            "type": "string"
51          },
52          "email_me_product": {
53            "type": "boolean"
54          },
55          "email_preferred": {
56            "type": "string"
57          },
58          "image": {
59            "type": "string"
60          },
61          "name": {
62            "type": "string"
63          },
64          "phone": {
65            "type": "string"
66          },
67          "provider": {
68            "type": "string"
69          },
70          "token": {
71            "type": "string"
72          }
73        },
74        "required": [
75          "email",
76          "provider",
77          "token",
78          "provider_uid",
79          "api_key"
80        ],
81        "title": "User",
82        "type": "object"
83      }
84    },
85    "required": [
86      "name"
87    ],
88    "title": "Team",
89    "type": "object"
90  }
91}

Delete Team

delete/api/teams/{token}

Path Parameters
  • token
    REQUIRED
    no type

    Team Token

Responses

Accepted Response

Fetch team

get/api/teams/{token}

Path Parameters
  • token
    REQUIRED
    no type

    Team Token

Responses

Team Response

1{
2  "schema": {
3    "properties": {
4      "name": {
5        "type": "string"
6      },
7      "team_users": {
8        "items": {
9          "properties": {
10            "email": {
11              "type": "string"
12            },
13            "name": {
14              "type": "string"
15            }
16          },
17          "required": [
18            "email",
19            "name"
20          ],
21          "title": "TeamUser",
22          "type": "object"
23        },
24        "type": "array"
25      },
26      "token": {
27        "type": "string"
28      },
29      "user": {
30        "properties": {
31          "api_key": {
32            "type": "string"
33          },
34          "api_quota": {
35            "type": "integer"
36          },
37          "bigquery_dataset_id": {
38            "type": "string"
39          },
40          "bigquery_dataset_location": {
41            "type": "string"
42          },
43          "bigquery_project_id": {
44            "type": "string"
45          },
46          "company": {
47            "type": "string"
48          },
49          "email": {
50            "type": "string"
51          },
52          "email_me_product": {
53            "type": "boolean"
54          },
55          "email_preferred": {
56            "type": "string"
57          },
58          "image": {
59            "type": "string"
60          },
61          "name": {
62            "type": "string"
63          },
64          "phone": {
65            "type": "string"
66          },
67          "provider": {
68            "type": "string"
69          },
70          "token": {
71            "type": "string"
72          }
73        },
74        "required": [
75          "email",
76          "provider",
77          "token",
78          "provider_uid",
79          "api_key"
80        ],
81        "title": "User",
82        "type": "object"
83      }
84    },
85    "required": [
86      "name"
87    ],
88    "title": "Team",
89    "type": "object"
90  }
91}

Update team

patch/api/teams/{token}

Path Parameters
  • token
    REQUIRED
    no type

    Team Token

Responses

Created Response

1{
2  "schema": {
3    "properties": {
4      "name": {
5        "type": "string"
6      },
7      "team_users": {
8        "items": {
9          "properties": {
10            "email": {
11              "type": "string"
12            },
13            "name": {
14              "type": "string"
15            }
16          },
17          "required": [
18            "email",
19            "name"
20          ],
21          "title": "TeamUser",
22          "type": "object"
23        },
24        "type": "array"
25      },
26      "token": {
27        "type": "string"
28      },
29      "user": {
30        "properties": {
31          "api_key": {
32            "type": "string"
33          },
34          "api_quota": {
35            "type": "integer"
36          },
37          "bigquery_dataset_id": {
38            "type": "string"
39          },
40          "bigquery_dataset_location": {
41            "type": "string"
42          },
43          "bigquery_project_id": {
44            "type": "string"
45          },
46          "company": {
47            "type": "string"
48          },
49          "email": {
50            "type": "string"
51          },
52          "email_me_product": {
53            "type": "boolean"
54          },
55          "email_preferred": {
56            "type": "string"
57          },
58          "image": {
59            "type": "string"
60          },
61          "name": {
62            "type": "string"
63          },
64          "phone": {
65            "type": "string"
66          },
67          "provider": {
68            "type": "string"
69          },
70          "token": {
71            "type": "string"
72          }
73        },
74        "required": [
75          "email",
76          "provider",
77          "token",
78          "provider_uid",
79          "api_key"
80        ],
81        "title": "User",
82        "type": "object"
83      }
84    },
85    "required": [
86      "name"
87    ],
88    "title": "Team",
89    "type": "object"
90  }
91}