> Canonical URL: https://codingcat.dev/post/firebase-2025-01-dataconnect-relationships

# How Relationships Work in Data Connect in Firebase: Web Architecture & Implementation Guide

![CodingCat.dev tutorial cover image](https://cdn.sanity.io/images/hfh83o0w/production/559c4c4b65b6678dd381afb5df2ec0c9ccea2c0d-1200x630.svg?w=1200&q=82&fit=max&auto=format)[![Alex Patterson](https://cdn.sanity.io/images/hfh83o0w/production/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)January 29, 2025

For years, choosing Firebase meant trading away relational SQL joins, strict foreign keys, and pgvector similarity search in favor of NoSQL document denormalization. Following the announcement of **How Relationships Work in Data Connect**  by Andrea Wu on the [**Official Firebase Blog**](https://firebase.blog/posts/2025/01/dataconnect-relationships/) (2025-01-28), here is our hands-on CodingCat.dev breakdown of what actually shipped, how it works under the hood, and how we wire it into production TypeScript, Next.js, Astro, SvelteKit, React, and Angular applications. Note: Firebase Data Connect has been renamed to SQL Connect. Learn more in the SQL Connect announcement.

## The Mental Model: Why How Relationships Work in Data Connect Matters for Web Devs

As a Google Developer Expert (GDE) for Firebase and Senior Solutions Engineer at CodingCat.dev, I evaluate every Firebase update through one lens: does it reduce boilerplate while keeping our runtime security and cloud bills predictable? Firebase Data Connect bridges that gap by pairing a managed Google Cloud SQL for PostgreSQL instance with a declarative GraphQL schema compiler that automatically generates type-safe TypeScript, React, and Angular SDKs alongside server-enforced @auth directives.

> AJ Pro-Tip from Alex: Keep your authorization logic inside your Data Connect GraphQL operations using @auth(level: USER) and server-evaluated expressions like auth.uid and request.time rather than trusting client-supplied user IDs in query variables.

## How It Works: Technical Breakdown & Implementation

One of the major benefits of using a SQL database is that relationships between data are clearly defined and organized. Firebase Data Connect supports relationships in schemas, queries, and mutations, and this blog post will dive into setting up your schema to reflect relationships. We’ll assume that you are familiar with [**schemas**](https://firebase.blog/posts/2024/10/dataconnect-graphql), and you can read the Data Connect [**documentation**](https://firebase.google.com/docs/data-connect/schemas-queries-mutations) if you need a refresher.

### Relationships in relational databases

In relational databases, each table has a primary key to identify each record in the table, and these primary keys can be used in other tables as a foreign key to refer back to the record with that primary key. This creates a relationship between the two tables. There are one-to-one, one-to-many, and many-to-many relationships, and we’ll go over each one and how to create such relationships in Data Connect.

### One-to-one relationships

In one-to-one relationships, one record in a table is associated with exactly one record in another table. For example, a “Movie” table that holds information about the movie such as title and genre can have a one-to-one relationship with a “Movie Metadata” table that keeps track of additional information such as the director, release year, and rating for each movie. A movie can have one metadata record, and each metadata is for one movie.

To define the relationship, the `Movie` table has a primary key that’s used in the `MovieMetadata` table. See this below where the `Movie` table with `movieId` as the primary key and a `MovieMetadata` table has `movieMetadataId` as its primary key. In the latter table, `movieId` is a foreign key, used to refer back to specific records in the `Movie` table.

With Data Connect, the `Movie` table looks like this:

```
type
  id: UUID! @default(expr: "uuidV4()")
  title: String!
  genre: String
}
```

You can leave the `id` field out, because Data Connect will automatically generate a primary key for you. The generated fields will be in `implicit.gql`. The code above can be simplified to:

```
type
  title: String!
  genre: String
}
```

If you open `implicit.gql`, there will be an `id` field in the extended `Movie` class:

```
extend
  id: UUID! @default(expr: "uuidV4()") @fdc_generated(from: "Movie",
  purpose: IMPLICIT_KEY_FIELD)
}
```

Next, let’s see what the `MovieMetadata` table without the foreign key from `Movie` looks like:

```
type
  director: String
  rating: Float
  releaseYear: Int
}
```

Again, an `id` primary key gets automatically created and put into `implicit.gql`:

```
extend
  id: UUID! @default(expr: "uuidV4()") @fdc_generated(from: "MovieMetadata", purpose: IMPLICIT_KEY_FIELD)
}
```

To add the foreign key with a one-to-one relationship, use `@unique`, which creates a field in the current table (`MovieMetadata`) and is a reference that holds the primary key of the referenced type:

```
type
  movie: Movie! @unique
  # movieId: UUID

As a result, the `movieId` from the `Movie` table will be included in this table, and the `movieId` will match the one in the `Movie` table.

### One-to-many relationships

In one-to-many relationships, one record in a table is associated with many records in another table. For example, let’s say there are users for your app, and each user can have one favorite movie while one movie can have many users for which it’s their favorite.

With Data Connect, the `User` table looks like this:

```
type
  id: String!
  username: String!
}
```

The `FavoriteMovie` table has this information:

```
type
  # User to FavoriteMovie is 1:1, as one user can have only one favorite movie
  user: User! @unique
  # userId: UUID

A combination of keys becomes the record’s unique identifier, the composite key. In this case for each record, the combination of user and movie needs to be unique, hence `key: ["user", "movie"]`.

You can reuse `@unique` to signal that all users should be unique in this `FavoriteMovie` table, since each user has one favorite movie. The movie field, however, does not need to be unique because one movie can be many users’ favorite movie (a many-to-many relationship, which gets covered in the next section).

`@ref` for `Movie` is similar to @unique, in that it creates a field in the current table (`FavoriteMovie`) to reference the primary key of the referenced type. In this case, `@ref(fields: "movieId", references: "id")` is implied:

- fields: “movieId” is the name of the foreign key received from the `Movie` table
- references: “id” means the `movieId` field is going to be the id from the `Movie` table

Writing `@ref` for `Movie` is optional, as it’s implied, so the former `FavoriteMovie` table’s code can be simplified to:

```
type
  user: User! @unique
  # userId: UUID

Whenever an implicit reference is made, `implicit.gql` includes the type:

```
extend
  userId: String! @fdc_generated(from: "FavoriteMovie.user", purpose: IMPLICIT_REF_FIELD)
  movieId: UUID! @fdc_generated(from: "FavoriteMovie.movie", purpose: IMPLICIT_REF_FIELD)
}
```

There is no `id` field since the combination of `userId` and `movieId` is the composite key for each record.

### Many-to-many relationships

In many-to-many relationships, many records in a table are associated with many records in another table, and typically, a join table is used to store these relations. An example of this is an actor being in many movies, and a movie having many actors. The table can hold additional information like whether the actor is a main or supporting actor for a movie.

With Data Connect, the `Actor` table looks like this:

```
type
  name: String!
}
```

We then create a join table between `Actor` and `MovieActors` to hold the many-to-many relationships information:

```
type
  movie: Movie!
  # movieId: UUID!

Again, we declare a composite key with `key: ["movie", "actor"]`, and there can be the same movie repeated multiple times in the table, same with actors. For each movie-actor pair, the table will say whether the actor is a main or supporting actor for that movie.

With the implied references, `implicit.gql` will extend the `MovieActor` class to include:

```
extend
  movieId: UUID! @fdc_generated(from: "MovieActor.movie", purpose: IMPLICIT_REF_FIELD)
  actorId: UUID! @fdc_generated(from: "MovieActor.actor", purpose: IMPLICIT_REF_FIELD)
}
```

## Production Web Architecture & Security Checklist

Whether we are deploying on [**Firebase App Hosting**](https://firebase.google.com/docs/app-hosting), Cloudflare Workers, or Vercel, shipping SQL features to production requires defense-in-depth across three layers:

- **Enforce Firebase App Check & Attestation: ** Protect your web endpoints, Cloud Functions, Data Connect GraphQL resolvers, and Firebase AI Logic calls against unauthorized replay or billing abuse using [**Firebase App Check with reCAPTCHA Enterprise**](https://firebase.google.com/docs/app-check).
- **Validate Locally with the Firebase Emulator Suite: ** Run deterministic integration tests against local Firestore, Auth, Functions, and Data Connect PostgreSQL emulators before promoting schema or rule changes to production.
- **Keep Server & Client Boundaries Type-Safe: ** Use the modular Firebase Web SDK and generated TypeScript bindings so SSR frameworks like Next.js, Astro, SvelteKit, and Angular serialize state cleanly without hydration flickers.

## Conclusion

Accelerate your full-stack web and AI development by pairing **How Relationships Work in Data Connect**  with strict Security Rules, Firebase App Check, and local emulator testing. Come tell us on [**X (@CodingCatDev)**](https://x.com/CodingCatDev) and [**LinkedIn (CodingCat.dev)**](https://www.linkedin.com/company/codingcatdev) how you are using Firebase in your stack, and subscribe to the [**CodingCat.dev YouTube Channel**](https://www.youtube.com/@CodingCatDev?sub_confirmation=1) so you don't miss what we build next!

## Watch Our Related Firebase Video Tutorial on YouTube

Want to see how we architect and debug Firebase web applications live? Watch our related CodingCat.dev session [**Firebase SQL with Data Connect**](https://youtu.be/N25khadfUag) below, and make sure to [**Subscribe to CodingCat.dev on YouTube**](https://www.youtube.com/@CodingCatDev?sub_confirmation=1) for weekly full-stack web and AI deep dives:

## Resources, Official Docs & Related CodingCat.dev Guides

- **Primary Release Source: ** [How Relationships Work in Data Connect on the Official Firebase Blog](https://firebase.blog/posts/2025/01/dataconnect-relationships/) (published 2025-01-28 by Andrea Wu)
- **Official Firebase Documentation: ** [Firebase Developer Docs & Web SDK Reference](https://firebase.google.com/docs/web/setup)
- **Related on CodingCat.dev: [Data Connect: All About Schemas](/post/firebase-2025-02-dataconnect-schemas)**
- **Related on CodingCat.dev: [Firebase SQL with Data Connect](/podcast/firebase-sql-with-data-connect)**
- **Related on CodingCat.dev: [Build a Custom No-Code App in 90 Minutes](/podcast/build-a-custom-no-code-app-in-90-minutes)**

## Frequently Asked Questions (FAQ)

### What are the key capabilities introduced in How Relationships Work in Data Connect?

How Relationships Work in Data Connect (announced 2025-01-28 by the Firebase team) enhances the platform for Firebase, Google Cloud, Web Dev, SQL workloads. Note: Firebase Data Connect has been renamed to SQL Connect. Learn more in the SQL Connect announcement. Developers can review the primary announcement on the [**Firebase Blog**](https://firebase.blog/posts/2025/01/dataconnect-relationships/) alongside our implementation patterns and production checklist above.

### How do web developers use How Relationships Work in Data Connect with Next.js, SvelteKit, React, or Angular?

Web developers can integrate these features using the modular Firebase JavaScript/TypeScript SDK, Firebase Data Connect web bindings, and [**Firebase App Hosting**](https://firebase.google.com/docs/app-hosting). Always pair client-side SDK initialization with Firebase App Check and strict Security Rules, and test locally with the Firebase Local Emulator Suite before deploying.

### Where can I watch video tutorials on Firebase Web and AI development?

You can watch our hands-on Firebase video walkthroughs on the [**CodingCat.dev YouTube Channel**](https://www.youtube.com/@CodingCatDev?sub_confirmation=1), including [**Firebase SQL with Data Connect**](https://youtu.be/N25khadfUag), and follow us on [**X (@CodingCatDev)**](https://x.com/CodingCatDev) for weekly full-stack tutorials.

## Recent Posts

[View More](/blog/page/1)[![PHP2Shell (CVE-2026-109618): How AI Found a Decade-Old Bug in 70% of the Web](https://cdn.sanity.io/images/hfh83o0w/production/e83065d0a4e2f841ce64d3f4aea8ddbbf07e5cb9-1376x768.jpg?w=1376&q=82&fit=max&auto=format)](/post/php2shell-cve-2026-109618-ai-php-security-scramble)

### [PHP2Shell (CVE-2026-109618): How AI Found a Decade-Old Bug in 70% of the Web](/post/php2shell-cve-2026-109618-ai-php-security-scramble)

October 22, 2026

Two critical pre-authentication RCE flaws in PHP (CVE-2026-109618 and CVE-2026-109619), uncovered by AI models from OpenAI and Google Gemini, sparked a global patching scramble across 70% of the web. Here is how PHP2Shell works and how to patch your servers.

[![Alex Patterson](https://cdn.sanity.io/images/hfh83o0w/production/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)[![Sanity Knowledge Bases](https://cdn.sanity.io/images/hfh83o0w/production/38b0f021c51d97043c8a1ebf31d505a0ea877b7c-2752x1536.jpg?w=1920&q=82&fit=max&auto=format)](/post/sanity-knowledge-bases)

### [Sanity Knowledge Bases](/post/sanity-knowledge-bases)

October 17, 2026

Eliminate query-time guessing in your AI agents. Learn how Sanity Context Knowledge Bases compile structured datasets, crawled documentation websites, and uploaded files ahead of time, resolve conflicting facts, and serve a compact outline over Context MCP.

[![Alex Patterson](https://cdn.sanity.io/images/hfh83o0w/production/a606dfaa381aab08ddbe16a33fe1d3e1fb37c927-400x400.jpg?w=96&h=96&q=82&fit=max&auto=format)Alex Patterson](/author/alex-patterson)