#Usin Sql

1 messages · Page 1 of 1 (latest)

royal ruin
#

Can you call external sql service with convex is that best practice

toxic horizonBOT
#

Hi @royal ruin. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

Yes, you can call an external SQL service (or any external API) from Convex, but it must be done through an action, not a query or mutation. Here's what you need to know:

How It Works

Convex functions are divided into three types, and only actions can make external API calls (fetch): [Convex Functions]

Queries Mutations Actions
Database access Yes Yes No
External API Calls (fetch) No No Yes

Best Practice Pattern

The recommended pattern is not to call an action directly from the client, but instead to:

  1. Trigger a mutation from the client — the mutation writes intent/state to the database and schedules the action.
  2. The scheduled action calls the external SQL service.
  3. The action writes results back via a mutation.
  4. A query on the client reactively picks up the new data. [Scheduler & Actions]

This is more robust because if the mutation fails, nothing is scheduled (transactional safety), and retries can be handled server-side rather than depending on the client. [Why Not Direct Actions]

Example

// mutation schedules the action
export const sendMessage = mutation({
  args: { topic: v.string() },
  handler: async (ctx, args) => {
    await ctx.db.insert("requests", { topic: args.topic });
    await ctx.scheduler.runAfter(0, internal.myModule.fetchFromExternalSQL, {
      topic: args.topic,
    });
  },
});
#

// action calls the external SQL service
export const fetchFromExternalSQL = internalAction({
args: { topic: v.string() },
handler: async (ctx, args) => {
const response = await fetch("https://your-sql-service.example.com/query", {
method: "POST",
body: JSON.stringify({ query: args.topic }),
});
const data = await response.json();

// Write results back via a mutation
await ctx.runMutation(internal.myModule.saveResults, { data });

},
});

[[Actions Docs](<https://docs.convex.dev/functions/actions>)]

## Key Takeaway

Keep actions **as small as possible** — only the part that requires the external call should live in the action. Most of your logic should stay in queries and mutations for scalability and transactional guarantees. [[Best Practices](<https://docs.convex.dev/tutorial/actions#the-scheduler-actions-and-the-sync-engine>)]
----------------------
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
----------------------