![Profile image for Ian Macartney](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
Ian works on Developer Experience at Convex. He has been a full stack freelancer at The New York Times and elsewhere, a backend engineer and technical lead at Dropbox, a mechanical engineer at MindTribe, and an iOS engineer before the term "iOS" even existed. He loves ideas and ergonomic tools.
All posts by Ian
Multiple apps on a single domain hosted on sub-paths![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Serve your app on a sub-path to host multiple apps on the same domain, using vercel.json rewrites.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
7 days ago
Streaming HTTP Responses using fetch![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Learn the basics of HTTP streaming with Convex by re-implementing OpenAI's SDK using built-in fetch and async iterators. No npm dependencies needed.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a month ago
The “full-stack framework” fallacy![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
When people want a full-stack framework, what they really want is an opinionated backend that interoperates seamlessly with their frontends in a way that empowers full-stack developers to easily build apps that can scale.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
2 months ago
Implementing Rate Limiting with only two numbers![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Implementing application rate limiting when you have fast access to a database with strong ACID guarantees. Token bucket and fixed window, with fairness, burst accommodation and fire-and-forget support.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
2 months ago
Work Stealing: Load-balancing for compute-heavy tasks![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Compare push-based load balancing with pull-based work stealing as scalable strategies for distributing resource-intensive workloads, such as running LLM models for AI apps.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
2 months ago
Implementing work stealing with a reactive database![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Implementing "work stealing" - a workload distribution strategy - using Convex's reactive database.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
2 months ago
Stateful Migrations using Mutations![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Online migrations in Convex using mutations. Including a helper to track migration state!
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
3 months ago
Operational maturity for production![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
This post will cover various aspects of operational maturity, and steps to take as your app grows up.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
4 months ago
Testing patterns for peace of mind![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Learn about best practices for testing your full-stack apps - running on Convex or elsewhere!
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
4 months ago
Observing your app in production![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
By setting up dedicated tools, you can get actionable data to help understanding errors, performance, user behavior and allow you respond quickly when things change.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
4 months ago
YOLO: Get to an MVP fast![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Before you burden yourself with “best practices” for large-scale companies, focus on what will reduce your feedback cycles and help you ship early and often. Think about your use case, not your toolbox.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
4 months ago
Lightweight Migrations![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Patch all of your data in your database table with the bulk edit feature on the Convex dashboard, without writing migration code.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
5 months ago
Convert your .json array to a .jsonl (JSON Lines)![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
JSON Lines stores one JSON object per line in a file, which is more scalable. Here's the one-liner to convert your .json file to .jsonl
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
5 months ago
Set up ESLint for best practices![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
ESLint is a powerful tool that goes beyond simply type checking. We go over how to set it up and implement some basic workflows with the
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
5 months ago
Queries that scale![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
As your app grows from tens to hundreds to thousands of users, there are some techniques that will keep your database queries snappy and efficient. I’ve put together a short list of the most common techniques used by teams scaling on Convex.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
5 months ago
Supercharge `npm run dev` with package.json scripts![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
With a simple `npm run dev` we can sign up a user for Convex, add seed data, and run the frontend and backend (including database) in parallel. Here's how we do it, and how to undo it too.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
6 months ago
Session Tracking Without Cookies![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Advice and resources for session tracking per-tab or per-browser via localStorage / sessionStorage using React Context, hooks, and some utilities to make your life easier.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
6 months ago
Using branded types in validators![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
If you have a more specific type than what you can express with Convex validators, you can still document that at the type level in Convex by casting once in your schema definition.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
6 months ago
Database Relationship Helpers![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Traverse database relationships in a readable, predictable, and debuggable way. Support for one-to-one, one-to-many, and many-to-many via utility functions available in convex-helpers.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
6 months ago
Zod with TypeScript for Server-side Validation and End-to-End Types![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Use Zod with TypeScript for argument validation on your server functions allows you to both protect against invalid data, and define TypeScript types that propagate to your client. This can now be used as an alternative to the built-in argument validation on Convex.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
7 months ago
Customizing serverless functions without middleware![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Re-use code and centralize request handler definitions with discoverability and type safety and without the indirection of middleware or nesting of wrappers. Use the new customFunction module in convex-helpers for your Convex TypeScript functions.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
7 months ago
Seeding Data for Preview Deployments![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Now that we've launched Preview Deployments on Convex, you can test out backend changes easier than ever. But you may want to seed your project with data first, so let's go over how to do that.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
9 months ago
GPT Streaming With Persistent Reactivity![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Stream GPT responses without brittle browser-based HTTP streaming.
Multiplayer reactivity, persistence, reactivity via Convex. Using OpenAI’s Node SDK server-side, and Convex's useQuery hook client-side.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
9 months ago
Using Pinecone and Embeddings![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Pinecone and Convex are a good match when you're looking to build an application that leverages embeddings and also has application data.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
The Magic of Embeddings![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Embeddings, why they’re useful, and how we can store and use them in Convex.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Relationship Structures: Let's Talk About Schemas![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
In this post we’ll look at some patterns for structuring relationships in the Convex database.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Intro to Migrations![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
There are as many ways to migrate data as there are databases, but here’s some basic information to set the stage.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
5 Dashboard Tricks![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Did you know you can use the Convex Dashboard to run functions, enter seed data, filter & delete data, upload files, and more?
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Moderating ChatGPT Content: Full-Stack![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
In this post, we’ll look at how to use the moderation API to flag messages before sending them to Chat-GPT, and patterns for handling these errors in a full-stack React app.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Adding Personality to ChatGPT-3![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
How to store multiple personalities Convex and provide them to the chatGPT API, enabling changing personalities mid-conversation. This is a follow-up to Building a full-stack ChatGPT app.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Building a Full-Stack ChatGPT app![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Let's build a full-stack chat app to talk to ChatGPT on its new API!
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Background Job Management![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Implement asynchronous job patterns using a table to track progress. Fire-and-forget, cancelation, timeouts, and more.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Anonymous Users via Sessions![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Getting users to sign up for a new service before seeing any benefits is challenging. In this post, we looked at a couple of strategies for managing user information without requiring a login.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Using Dall-E from Convex![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Use Convex to fetch an image from OpenAI’s image generation service based on a user-provided prompt.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Building a Multiplayer Game![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Building multiplayer games requires a lot of synchronization logic and event systems. However, using Convex, we get a lot of this for free! Follow along here as we build a complex multiplayer game on Convex, leveraging its reactive-by-default queries, transactional mutations, backend storage, and scheduled functions.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Sessions: Wrappers as "Middleware"![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
An approach to server-persisted session data with Convex, wrapping your server functions and storing a session ID on the client.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
a year ago
Zod Validation: Wrappers as “Middleware”![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Function validation is important for a production app because you can’t always control which clients are talking to your server. See how to use zod to validate your Convex functions, using our withZod wrapper.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
2 years ago
Authentication: Wrappers as “Middleware”![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Using wrapper functions like withUser can help you organize your code into middleware-like blocks that you can compose to keep your function logic concise.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
2 years ago
Implementing Presence with Convex![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Some patterns for incorporating presence into a web app leveraging Convex, and sharing some tips & utilities I built along the way.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
2 years ago
Throttling Requests by Single-Flighting![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
For write-heavy applications, use single flighting to dynamically throttle requests. See how we implement this with React hooks for Convex.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
2 years ago
Launching Features Right on Time: Feature Gating![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Today we’re going to talk about how to flip features on and off remotely using a clever use of the reactive nature of Convex queries.
![Ian Macartney's Profile image](/_next/image?url=https%3A%2F%2Fcdn.sanity.io%2Fimages%2Fts10onj4%2Fproduction%2F077753b63476b77fb111ba06d1bb538517033a54-3500x3500.jpg&w=3840&q=75)
Ian Macartney
2 years ago