What DBs does Redwood Support?

The idea of linking in multiple APIs into the same GraphQL schema gives me some strong Gatsby / Gridsome vibes. I wonder if it would be useful to add support to just drop Gatsby plugins (which already exist for sites like Contentful, etc) into Redwood, to provide access to these APIs without having to reimplement this thing again and again.

1 Like

Hi @sam Yes indeed some similar vibes :+1:

I’m not familiar with Gridsome, but for Gatsby I do know there’s a lot going on under the hood to implement GraphQL given the unique framework design. My suspicion is that there’d be redundant complexity in the way, effectively “wrapping a wrapper”.

Given our roadmap of core features we’ve yet to build for Redwood, I can’t foresee us getting to experiment with this any time soon. But we’d welcome a POC and can definitely offer feedback/direction along the way. Just keep us posted if that’s something you’re able to try.

1 Like

Wondering if anyone has tried to deploy a Redwood app with something aside from Heroku Postgres as detailed in the tutorial? I saw some discussion around deploying without a database and some limitations around AWS DBs.

I’m going to be working on building a Redwood project with Fauna over the next two weeks and was hoping to get some tips on any gotchas that might be coming at me. As far as I can tell there’s been a lot of talk about getting Redwood to work with NoSQL DBs but nothing concrete yet.

1 Like

Hey Anthony! I don’t know of too many other custom DB integrations besides this one: Using Redwood with Neo4j Database

At this time, and I’m guessing you know, Fauna is not supported by Prisma (yet). So you’ll have to setup your own connection, which is definitely possible. Please do start a Forum topic and keep us posted as you go – there’s a lot of interest in Fauna and I’m sure a lot of people will be curious to both help and learn from your experiment.

I know people are using Redwood currently with DigitalOcean and AWS. I haven’t heard of anyone using Azure DB or Google Cloud DB. But as long as it’s relational (and not MSQL) it is supported by Prisma.

Personally, I’m excited about MongoDB support from Prisma as I’m a big fan of the MongoDB Atlas service.

I tried integrating the tutorial blog post app with Azure for Postgres, at first glance it works well :slight_smile: Haven’t done anything prod-worthy with it, but at least I know it’s possible :smiley: I basically followed the Deployment section of the tutorial with a few Azure-specific notes here and there (thank you for writing such a well-detailed tutorial! :rocket:)

4 Likes

Nice! Thanks for the update and sounds like progress :rocket:

Curious if you tried (or if there’s an option) to configure anything in front of Azure Postgres for handling connection pooling/load? Here’s the RW related Doc: https://redwoodjs.com/docs/local-postgres-setup

I’m no expert, but the gist is that in a serverless environment the front-end connections could spin up an unlimited number of connections and slam the DB.

People using DigitalOcean have said PG Bouncer is working really well. On AWS is the Amazon RDS Proxy.

Does it look like Azure provides something similar?

Nothing broke when I added the connection_limit=1 parameter, but I haven’t tried opening multiple connections to the database either :woman_shrugging:

It doesn’t seem like Azure provides a service similar to Amazon RDS Proxy (yet). Actually, I found a tutorial for setting up PgBouncer for Azure DB for PostgreSQL :smiley: and Citus mentions it as their preferred connection pooler in this blog post, back from before they became part of Azure’s Postgres solutions.

Ah, good to know. And thanks for looking into it! I don’t think it’s needed right now by any means. But once Azure seems to be working for Redwood deploy then looking into connection pooling could be a good follow-on step.

Hope all’s well. And have a good weekend!

1 Like

Hi @ajcwebdev. Curious how Fauna + RW is working out?

I’ve given Fauna some thoughts and wonder if you have had the same.

RW’s web side talks to the api side over graphql. Cool.

The api side can talk to datastores via services + sdl. Also cool.

Out of the box, Prisma is supported since there is a readily available db client to import and write queries/mutations.

But, a service is a service. My SDL can define the queries, but I don’t have to use the Prisma db client. I could use the Contentful SDK – or call another graphql endpoint (Hasura … or Fauna … or Contentful for that matter) using graphql-request.

I’ve shared this example here before, but my I made an app a year or so ago where 8 year old niece uses Contentful to keep track of little Disney Princess cupcake characters she build from pieces of a board game. The SDL is:

import gql from 'graphql-tag'

export const schema = gql`
  type Cupcake {
    id: String!
    name: String!
    description: String!
    price: Float
    rating: Int
    slug: String!
    photos: [ContentfulAsset]
  }
  type Query {
    cupcakes: [Cupcake!]!
    cupcake(id: String!): Cupcake!
  }
`

and the service that uses their SDK is:

import { createClient } from 'contentful'

const client = createClient({
  space: process.env.CONTENTFUL_SPACE,
  accessToken: process.env.CONTENTFUL_DELIVERY_API_KEY,
})

const renderAsset = (fields) => {
  return { title: fields.title, file: fields.file }
}

const renderAssets = (assets) => {
  return assets.map((asset) => renderAsset(asset.fields))
}

const renderEntry = (entry) => {
  return {
    id: entry.sys.id,
    name: entry.fields.name,
    description: entry.fields.description,
    price: entry.fields.price,
    rating: entry.fields.rating,
    slug: entry.fields.slug,
    photos: renderAssets(entry.fields.photos),
  }
}

export const cupcakes = async () => {
  const response = await client.getEntries({
    content_type: 'cupcake',
    limit: 1000,
    order: 'fields.name',
  })

  return response.items.map((entry) => renderEntry(entry))
}

export const cupcake = async ({ id }) => {
  const entry = await client.getEntry(id)

  return renderEntry(entry)
}

and then I can use RW cells just as I would if I was querying a Prisma Postgres database:

import Cupcake from 'src/components/Cupcake'

export const QUERY = gql`
  query {
    cupcakes {
      id
      name
      description
      price
      rating
      slug
      photos {
        title
        file {
          url
        }
      }
    }
  }
`

export const Loading = () => {
  return (
    <Stack>
      <Box mb={6} maxW="sm" overflow="hidden">
        <Box p="6">
          <Skeleton height="20px" my="10px" />
        </Box>
      </Box>
      <Box mb={6} maxW="sm" overflow="hidden">
        <Box p="6">
          <Skeleton height="20px" my="10px" />
        </Box>
      </Box>
      <Box mb={6} maxW="sm" overflow="hidden">
        <Box p="6">
          <Skeleton height="20px" my="10px" />
        </Box>
      </Box>
    </Stack>
  )
}

export const Empty = () => <div>Empty</div>

export const Failure = ({ error }) => <div>Error: {error.message}</div>

export const Success = ({ cupcakes }) => {
  return cupcakes.map((cupcake) => (
    <Cupcake key={cupcake.id} cupcake={cupcake}></Cupcake>
  ))
}

Or, if I wanted to call another GraphQL endpoint, in this case a PG-backed view served by Hasura for “daily story counts” my SDL is:

import gql from 'graphql-tag'

export const schema = gql`
  type Calendar {
    day: String!
    value: Int!
  }
  type Query {
    dailyStoryCounts: [Calendar!]!
  }
`

I then have a Hasura client (just like a lib/db)

import { GraphQLClient } from 'graphql-request'

export const request = async (
  query = {},
  domain = process.env.HASURA_DOMAIN
) => {
  const endpoint = `https://${domain}/v1/graphql`

  const graphQLClient = new GraphQLClient(endpoint, {
    headers: {
      'x-hasura-admin-secret': process.env.HASURA_KEY,
    },
  })

  try {
    return await graphQLClient.request(query)
  } catch (error) {
    console.log(error)
    return error
  }
}

Then my service uses that client to fetch:

import { request } from 'src/lib/hasuraClient'

export const dailyStoryCounts = async () => {
  const query = `
  {
    dailyStoryCounts: calendar {
      day: date
      value
    }
  }
 `
  const data = await request(query, process.env.HASURA_DOMAIN)

  return data['dailyStoryCounts']
}

and my cells is normal and can render a nice calendar chart:

import { Box } from '@chakra-ui/core'
import { ResponsiveCalendar } from '@nivo/calendar'

export const QUERY = gql`
  query {
    dailyStoryCounts {
      day
      value
    }
  }
`

export const Loading = () => <div>Loading...</div>

export const Empty = () => <div>Empty</div>

export const Failure = ({ error }) => <div>Error: {error.message}</div>

export const Success = ({ dailyStoryCounts }) => {
  const firstDay = dailyStoryCounts[0].day
  const lastDay = dailyStoryCounts[dailyStoryCounts.length - 1].day

  return (
    <Box height="600px" width="100%">
      <ResponsiveCalendar
        data={dailyStoryCounts}
        from={firstDay}
        to={lastDay}
        emptyColor="#eeeeee"
        colors={['#61cdbb', '#97e3d5', '#e8c1a0', '#f47560']}
        margin={{ top: 40, right: 40, bottom: 40, left: 40 }}
        yearSpacing={40}
        monthBorderColor="#ffffff"
        dayBorderWidth={2}
        dayBorderColor="#ffffff"
        legends={[
          {
            anchor: 'bottom-right',
            direction: 'row',
            translateY: 36,
            itemCount: 4,
            itemWidth: 42,
            itemHeight: 36,
            itemsSpacing: 14,
            itemDirection: 'right-to-left',
          },
        ]}
      />
    </Box>
  )
}

(note: I turned off data in July)

Ok. That was long winded, I know.

But, to implement Fauna right now I would either:

  • use the Fauna client and write FQL (ie, the Contentful SDK approach)
  • make a gql client and write graphql against Fauna (the Hasura approach)

What I don’t think I would want is for the web to call Fauna directly or RW’s graphql to somehow relay the gql to Fauna. Do I? Don’t think so, but I have not experimented.

But what I think is super super cool is that I think if I had services that talked to Contentful (cupcakes) and Hasura (stories) and Prisma/Postgres (users), I am pretty sure I could make a single graphql request from a cell like

   query {
     cupcakes {
       id
       name
     }
 
    stories {
     id
     title
    }

    users {
      id 
      email
    }
}

And I could render all the data from three different sources in a Dashboard cell like:

export const Success = ({ cupcakes, stories, users }) => {
}

And if the id’s somehow matched, I could probably even filter: give me stories this user wrote about these cupcakes.

That’s really really cool.

BTW - this is Monty: “Monty likes to play in the woods to hide from his sister Minty.”

1 Like

Awesome, that was very, very helpful, and definitely not long winded. My goal here is to create a tutorial for Fauna to get Fauna users up and running with Redwood as easily as possible. So I think the FQL approach is more appealing to me here since we’ll be more on Fauna’s turf so to speak.

I’d want to explore the gql client approach as well because that would be more agnostic. As David was saying we’ll want to figure out Mongo and other DBs, and since Fauna is a document store there’s cross-over there, but the query languages are totally different.

1 Like

Same here.

FQL is really strange (least to me coming from SQL) at first, but I got used to it for basic queries. Figuring out the equivalent of joins still makes my head hurt a bit.

Plus (I think) to support GraphQL in Fauna one has to create a schema – so that would not be the “up and running with Redwood as easily as possible” case.

That reminds me – looking at some of the FQL I did – pagination. I need to explore how to do that in RW.

Yeah I’m always hesitant to invest in learning any DSL but it’s hard to avoid with databases, even those that follow the SQL spec end up with slightly different implementations since the spec is ambiguous.

Thankfully Fauna has really invested in their docs and blog articles, I’m going through this series right now to get up to speed. Not sure how deep you’ve gotten into their material but they’ve got a section on pagination that should be helpful.

Just a heads up, @thedavid, your link to prisma2’s supported database list in the first post of this Topic is a dead link and gives you a redirect to Prisma’s docs. If you click the “Edit this page on Github” link you’ll find the new place on Github the content lives.

Looks like they did a rearrangement cause they originally had a docs folder inside the prisma repo but wanted to have a dedicated docs repo by itself.

1 Like

Thanks for the heads up. Updated OP with new website page.

Wanted to add this here to complete the story since recently a guide: https://fauna.com/blog/building-a-minimum-viable-stack-with-redwoodjs-and-faunadb
came out on how to use RedwoodJS with FaunaDB. :heart_eyes:
The guide bypasses Prisma if I understood correctly.

2 Likes

Hey Brecht, thanks for the link! You are correct, the project has you delete all the Prisma directories and code and we query the Fauna GraphQL API directly. I had a blast making the project and the whole Fauna team was incredible to work with.

2 Likes

I recently did some research into what the situation was with MongoDB and Prisma that wasn’t directly about Redwood but should still be pretty relevant to the discussion here. I asked some big picture questions and Nikolas Burke gave a really great response that’s worth sharing here.

TL:DR Prisma+Mongo is super duper hard and learn Rust


Hey Anthony :wave: thank you so much for this great writeup and for summarizing the comments from the issue :pray: We are very aware that people are eagerly waiting for MongoDB support in Prisma 2! I want to shed some light on the current situation and how we are currently thinking about a MongoDB connector by responding to your questions.

Does Prisma need anything else from MongoDB to implement a connector or is the MongoDB Rust driver good to go?

As far as I’m aware, we don’t need anything else from MongoDB on a technical level.

Is anyone at Prisma currently working on a MongoDB connector or accountable for tracking its progress?

We are not actively working on a MongoDB connector at the moment. This is also reflected on our roadmap.

Note that there are a few technical prerequisites for the MongoDB connector, such as the ability to use native database types in the Prisma schema (the good news is that this is under active development and likely to be released within the next 2-3 months). Another feature that we need to get done before we can get serious about a MongoDB connector is Prisma Migrate. Migrations for SQL and NoSQL databases mean very different things. We need to be confident about our solution for SQL databases before we can “afford” expanding to NoSQL ones.

If not what can contributors do to help Prisma out?

Unfortunately I believe there’s not much that contributors can do at this point, unless they have a lot of free time and come equipped with some very solid knowledge about Rust, JS/TS and databases altogether.

While Prisma is open source, the software we’re building is extremely complex. The onboarding processs for new developers who need to get into our codebase typically taskes several days/weeks until there’s a level of familiarity where they can independently contribute. In that sense, it seems practically impossible that somebody who’s not part of our engineering orgnization would be able to grasp the complexity of the codebase and would be able to contribute. We are aware that this is not ideal though and one of our internal engineering initiatives for the next months is to start better documenting the internals of Prisma – hopefully this will make it easier for external folks to contribute in the future!

However, I actually think that the complexity of the codebase is not the main problem in this case. The bigger one is that there a lot of unknowns and unresolved “product questions”. The Prisma schema as well as the Prisma Client API are currently optimized for relational databases. MongoDB brings a new database paradigm and we’ll need to figure out how this can play nicely together with our existing tools.

So, what can you do to help?

Talk to our product team! Share your thoughts about the MongoDB connector with the product team directly or keep commenting in the GitHub issue. Your input will be the foundation for what we’re building, so if you’re eagerly waiting for the MongoDB connector, th best thing you can do right now is help us figure out what it actually should look like and how it should work.

As I said, we are very aware that people want MongoDB support (so do we :smile:), but there are a few roadblocks we need to get out of the way before we can start serious development on it.

Mongo support is getting here slowly but surely. The Prisma team is accepting applications for user testing and amazingly enough Gautam Singh has, against all odds, rolled his own solution with Prisma and Keystone.

1 Like

I think of the coupling with Prisma as the blocker from going full polyglot db. It’s a flexible ORM/driver for a good subset of tried and true databases, but any robust app is polyglot and sources data from multiple aggregates. Moreover, not every team will buy-in on Prisma-- so even if you get it into a project, it’s often running on its own and needs to compromise due to external migrations coming from another codebase.

I also think that the db compatibility issue can be solved by GraphQL alone w/ aid from the framework to enhance dev experience and doesn’t require DB-development chops as long as there is a robust JS driver for the DB itself.

GraphQL’s promise is to adapt any and all data sources into 1 easily usable and dev-experience focused pattern that can be write + read optimized. The tight binding w/ Prisma in this case somewhat undoes that because of the inflexibility in DBs. Prisma is nice because it normalizes DSL for a variety of relational DBs, but the support isn’t enough and in a lot of cases, full parity probably isn’t possible. The DSL philosophy is relational and may not be immediately compatible with nosql patterns as seen by the relative slow development of the MongoDB driver (which I bet is a lot like jamming a square peg into a triangle hole).

If I could just fill out some core generalized boilerplate that allows me to rock n roll with any data source + multiple data sources, RW would be such an easy sell for any team. What that possibly looks like to me is a decoupled /services folder with resolvers that can access any data source I want and 1 gql schema folder where I create my SDLs without worrying about anything else but the schema.

Hey wait a minute… the framework is like 85% there!

Databases RedwoodJS Supports as of Early 2022

Over the last two years, the amount of ways to connect to a database with Redwood and the amount of ways to deploy and host that database have increased tremendously.

Supported by Prisma

Prisma has expanded their list of relational/SQL options and started introducing non-relational databases.

Databases with GraphQL Endpoints

For databases that Prisma doesn’t support, the Redwood GraphQL API can be used to query any database that exposes a GraphQL endpoint, whether the underlying database is SQL or NoSQL.

1 Like