February 26, 2025

PostGIS, Webhooks, Networking, and new AI models

Yesterday Elvis shared about the background and motivation for the rename, but the release itself is also full of exciting new capabilities, including big updates to our extensions and standard library. This release introduces support for PostGIS, a popular geospatial extension for Postgres, along with updates to our Auth extension and a new standard library module for asynchronous networking, starting with HTTP. We've also updated our preconfigured list of AI models to synchronize with the latest and greatest from OpenAI, Anthropic, and Mistral.

PostGIS is a popular extension for PostgreSQL that adds support for geographic data types and functions. It has been a highly requested integration for Gel. Now, by installing the extension in your instance, you can access the full PostGIS feature set with first-class support for Gel's native type system.

Copy
$ 
gel extension install postgis

Then add the extension to your schema:

Copy
using extension postgis;

Here's an example of getting a PostGIS GeometryCollection of the 10 closest coffee shops to a location, and where the diameter of the circle is the rating of the coffee shop, and the circle is centered on the shop's location.

Copy
with
  gel_hq := ext::postgis::point(
    -122.405194,
    37.792833
  ),
  closest_coffee := (
    select Restaurant {
      distance := ext::postgis::distance(
        .coordinates,
        gel_hq
      ),
    }
    filter 'coffee' in .categories.tag
    order by .distance
    limit 10
  )
select ext::postgis::collect(
  array_agg((
    for restaurant in closest_coffee
    select ext::postgis::force3dm(
      restaurant.coordinates,
      restaurant.rating
    )
  ))
)

We've updated our UI with powerful visualization tools for viewing, and interacting with query results that contain PostGIS geometries.

We've introduced webhooks for auth lifecycle events. The primary use case, and the one we designed this feature around, is the ability to send fully custom emails for flows like verification, password reset, and more. Now you can craft messages that perfectly match your brand voice and application design. These webhooks integrate seamlessly with various points in the authentication flow, opening up possibilities for analytics tracking and third-party integrations.

Here is an example of how to configure a webhook to send emails for verification and password reset events.

Copy
configure current branch
insert ext::auth::WebhookConfig {
  url := 'http://localhost:8000/auth/webhook',
  events := {
    ext::auth::WebhookEvent.EmailVerificationRequested,
    ext::auth::WebhookEvent.PasswordResetRequested,
  },
};

We've also expanded our OpenID Connect support. You can now define generic providers that conform to the OpenID Connect spec, making integration with diverse identity providers straightforward.

Copy
configure current branch
insert ext::auth::OpenIDConnectProvider {
  secret := 'shhhh_top_secret',
  client_id := 'beep_boop_beep',
  name := 'generic_oidc',
  display_name := 'My Generic OIDC Provider',
  logo_url := 'https://example.com/logo.png',
  issuer_url := 'https://example.com',
  additional_scope := 'custom_provider_scope_string',
};

A small but useful change, we now pass along the validated id_token when provided by the provider, such as during the OpenID Connect flow. This can eliminate an extra roundtrip to the provider when fetching additional user information. All providers that use an id_token will automatically include it in the response, even if you haven't configured them as a custom OpenID Connect provider, so using existing providers like Google and Apple will now return the id_token in the response.

  • Sign-up flows are more developer-friendly too. Every successful sign-up response now includes the newly created ext::auth::Identity ID, simplifying the process of associating your application's User objects with the created identity. This change allows you to complete the sign-up flow immediately, even if email verification is required. If the user verifies their email from a different browser or device, they can simply log in after verification, treating the verification as a separate step from sign-up.

  • For those using our cloud service, we've removed a common development hurdle. A pre-configured development-only SMTP provider comes ready out of the box, letting you test email flows immediately. While this server is rate-limited and not intended for production use, it eliminates a significant setup step during the development phase.

To support the new auth webhooks, we've introduced a new standard library for asynchronous networking, starting with HTTP. This library includes a function that schedules an HTTP request and stores the result as an object. You can use this new functionality in triggers to integrate with external services, add auditing, and more.

Copy
with request := (
  net::http::schedule_request(
    'https://example.com',
    method := net::http::Method.POST,
    headers := [('Content-Type', 'application/json')],
    body := to_bytes($${"key": "value"}$$),
  )
)
select request.id;

You can now poll for responses using the request.id returned from that query:

Copy
with request := <net::http::ScheduledRequest><uuid>$request_id,
select request {
  state,
  failure,
  response: {
    status,
    body,
  }
} filter .state in {
  net::RequestState.Completed,
  net::RequestState.Failed,
};

We've updated our preconfigured list of AI models to synchronize with the latest models from OpenAI and Mistral.

ext::ai

Vendor

Model Name

ext::ai::OpenAI_O1_PreviewModel

OpenAI

o1-preview

ext::ai::OpenAI_O1_MiniModel

OpenAI

o1-mini

ext::ai::PixtralLargeModel

Mistral

pixtral-large-latest

ext::ai::Ministral_8B_Model

Mistral

ministral-8b-latest

ext::ai::CodestralModel

Mistral

codestral-latest

The world of LLM models is rapidly evolving, so as a reminder, you do not need to wait for us to update our preconfigured list of models to use the latest and greatest. You can configure your own models using our abstract types.

default.gel
Configure instance to use the new model
Copy
module default {
  abstract type Claude37SonnetModel
    extending ext::ai::TextGenerationModel {
      annotation
        ext::ai::model_name := "claude-3-7-sonnet-latest";
      annotation
        ext::ai::model_provider := "anthropic";
      annotation
        ext::ai::text_gen_model_context_window := "200000";
    };
}
Copy
configure current branch
insert ext::ai::CustomProviderConfig {
  name := 'claude-3-7-sonnet-latest',
  display_name := 'Claude 3.7 Sonnet',
  api_url := 'https://api.anthropic.com/v1',
  secret := 'sk-ant-api03-...',
};

We're excited to see what you all build with these new features, and stay tuned for more announcements during the rest of our launch week.

ShareTweet