How to make a FastFlag/Dynamic FastFlag system

Tutorial: How to make a FastFlag/Dynamic FastFlag system!

Intro

What is a FastFlag/Dynamic FastFlag?

FastFlags (also known has FFlags) and Dynamic FastFlags (also known as DFFlags) are a simple method for testing new features in your games. Roblox uses these to test new updates. You can mess around with FFlags to test new features. It’s also a great way of seeing if a new issue is caused by a newly released feature. @evaera made a tool for this, actually.

These are very useful, as you might want to make a new update, but be able to quickly disable it without actually updating your own game, and shutting down servers.

My team and I ran across this problem working on our latest game; we wanted to be able to disable and enable certain maps quickly. I ended up creating the code for this, and realized this could be quite useful, so I am making a tutorial on how to do it.

What is the difference between a FFlag and a DFFlag?

FFlag’s are settings that are switched on and take effect when a new server is created. If you switch a flag from true to false, it will not affect and servers that are currently running, just new severs. Example:

DFFlag’s are settings that update every 5 minutes, so if you make a change to a flag, within 5 minutes, the change will be on all new servers. It’s possible to bring that 5 minute time down from 5 minutes, if you use firebase hosting, but for this tutorial I will just be using GitHub.

That’s great, but why would I want to use them?

Often times, a new update may not be going as planned, and you may have to quickly update your game, and depending on how serious the issue is, you may need to shutdown all servers. This could ruin your player count. If you set up the code within a DFFlag statement, it could work as a system so you could remotely shut off that update with a simple command within a code editor.

It’s also great for testing new things; this is mainly how I’ve used it. My game has many different maps, some complete, some not. I want to be able to turn them on and off quickly, if I notice an issue with one map or I simply want to limit people from playing it because I get bug reports about. The possibilities with this are endless!

How does this work?

I’ll be explaining it a lot more in the tutorial, but here’s a short summary:

Using HttpService, I am sending a GET request to a .JSON document containing true/false statements. I can easily open up visual studio code, change a flag from true to false, commit, push, and then within 5 minutes this change goes into effect. (I would make a video on it, but it’d just be 5 minutes of nothing… and then something right at the end!)

What do I need to get set up?

You need:

  1. A code editor, preferably visual studio code.
  2. A GitHub account.
  3. Have Git installed.
  4. Your preferred way of writing code into Roblox studio.

Alright, let’s get started!

Part 1 – Setup

Step 1

Open up GitHub on your web browser, and create a new repository:

Then, name your repository, and make sure to make it public, otherwise this will not work.

Once you’ve created the repository, you’ll see a scary-looking screen-- don’t panic! Copy and paste the code on the second section, as shown below:

Step 2

Now that you’ve copied the text, open Visual Studio Code, and click “clone repository:”

Now, click “Clone from GitHub”, and type in the name of the repository you’ve created, starting with your username, then a "/’, then the name of the repository.

It will then prompt file editor to open. Create a new folder by right-clicking, rename it, and select it:

Then a pop-up will show up at the bottom right of your screen. Go ahead and click “open”:

Your now inside the repository!

Step 3

Now that you are inside, go ahead and create a new file in that folder:

Name it whatever you want, but make it end in .JSON. Hit enter, and it will open. For now, just put a basic data structure in the file, something similar to below:

{
    "test": true
}

Now, we are going to commit the change and push it to GitHub. Click the button on the side that looks similar to a branch:

Enter a commit message and click the checkmark:

Doing this will now mean the file is ready to be pushed. Click the 3 dots near the reload sign, then click “Push”:

The file has now been sent to GitHub. :slightly_smiling_face: Do this every time you want to edit a flag.

Step 4

We are now going to navigate back to our web browser and to the GitHub repository we just set up. Make sure you reload the page!

Next, click on the file that you just created inside visual studio.

oJ2iyJ5sHt

Once you have done this, navigate to the button that says “Raw”, and click it.

A new page will open, this is the raw file, and where we will be send our GET request’s to. Make sure to copy the URL in the browser, we will use that later!

Step 5

It’s now time to setup studio.

Make a basic baseplate, and open the file. Then go to “Game Settings”, and select:

Part 2 – DFFlags

Step 1

Start by adding a script to this new place. Place the Server Script into ServerScriptStorage.

Now, start out the script by creating a variable for HttpService:

local HttpService = game:GetService("HttpService")

(I will add onto the script every time, then do a more detailed walkthrough.)

After that, we will create a function called request() which will do the majority of the work in the script. We will be using :RequestAsync() which is a function of HttpService.

Add the following to your code:

local HttpService = game:GetService("HttpService")

local function request()
	local response = HttpService:RequestAsync(
		{
			Url = "you_url_here",
			Method = "GET",		
			Headers = {

				["Cache-Control"] = "no-cache"

			}
		}
	)

Make sure to replace the your_url_here with the URL discussed earlier. This code sends the GET request to the raw JSON file from github. It returns it in the JSON format, which Lua does not understand. That is what is dealt with later on.

Now it’s time to actually make the simple response to the webhook. Your code should now be at this:

local HttpService = game:GetService("HttpService")

local function request()
	local response = HttpService:RequestAsync(
		{
			Url = "https://raw.githubusercontent.com/FxllenCode/TheInternFFlags/main/fflags.json",
			Method = "GET",		
			Headers = {

				["Cache-Control"] = "no-cache"

			}
		}
	)


	if response.Success then
		print("Status code:", response.StatusCode, response.StatusMessage) -- printing status code 
		local data = HttpService:JSONDecode(response.Body) -- parse the JSON into Lua
		if data.test == true then
			print("Test is True.")
			-- whatever else you want to do here
		elseif	data.test == false then
			print("Test is False.")
			-- whatever else you want to do here
		end
	else
		print("The request failed:", response.StatusCode, response.StatusMessage) -- error handling
	end
end

Let’s dig into the code. If you want to actually learn from what’s happening, you should read the comments. That will help explain what is going on at each stage.

This code controls what flags you want to dynamically check for. In my case, I’m checking to see if “test” in my JSON file is true. If it’s true, I am printing that. It’s it’s false, I print that it’s false. This can be replaced with whatever you want your flags to check. There is also error handling, so if there is an issue, it doesn’t go without being identified.

This is all great, but the function isn’t being ran multiple times. It’s time to do this. Here is the final code for the DFFlag system:

local HttpService = game:GetService("HttpService")

local function request()
	local response = HttpService:RequestAsync(
		{
			Url = "https://raw.githubusercontent.com/FxllenCode/TheInternFFlags/main/fflags.json",
			Method = "GET",		
			Headers = {

				["Cache-Control"] = "no-cache"

			}
		}
	)


	if response.Success then
		print("Status code:", response.StatusCode, response.StatusMessage) -- printing status code 
		local data = HttpService:JSONDecode(response.Body) -- parse the JSON into Lua
		if data.test == true then
			print("Test is True.")
			-- whatever else you want to do here
		elseif	data.test == false then
			print("Test is False.")
			-- whatever else you want to do here
		end
	else
		warn("The request failed:", response.StatusCode, response.StatusMessage) -- error handling
	end
end

while true do

	local success, message = pcall(request)
	if not success then
		warn("Http Request failed:", message)
	end

	wait(300)
end

Here are some important things to note in the changes:

We are using pcall's in this case. Pcall is a very important feature, as if there is an internal error at Roblox, we don’t want the entire script to break. By wrapping the function in a pcall, an error will not break the entire script.

In addition the script is running once every 5 minutes (300 seconds). This is because GitHub does not update it’s raw files in less than 5 minutes, so it’s pointless to make the requests if it’s certain that the file will not be updated.

This concludes the DFFlags!

Part 3 – FFlags

Step 1

FFlags are quite simple. Create a new script in ServerScriptService.

Start out by defining HttpService, like so:

local HttpService = game:GetService("HttpService")

After this, take the URL you copied from earlier, and put it as the value of FFLAG_URL:

local HttpService = game:GetService("HttpService")

local FFLAG_URL = "your_url_here"

Then, simply make the GET request and then parse the raw JSON via HttpService:

local HttpService = game:GetService("HttpService")

local FFLAG_URL = "https://raw.githubusercontent.com/FxllenCode/TheInternFFlags/main/fflags.json"

local response = HttpService:GetAsync(FFLAG_URL)

local data = HttpService:JSONDecode(response)

This will return data in Lua format, so it can easily be accessed. For example purpose, all I am making the code do is print “test” if the test FFlag is true:

local HttpService = game:GetService("HttpService")

local FFLAG_URL = "https://raw.githubusercontent.com/FxllenCode/TheInternFFlags/main/fflags.json"

local response = HttpService:GetAsync(FFLAG_URL)

local data = HttpService:JSONDecode(response)

if data.test == true then
	
	print("Test")
	
end

You can do whatever you want here, but it is important to note that it is only run once, at the start up of the server.

Part 4 – Workflow Details

Changing a FFlag's value

It’s simple to change the value of a FFlag. Follow Step 3 of Part 1; every time you want to change a flag, change the value, commit, and then push. Once you have done this, the change is in place, and if it’s a DFFlag, the server will recognize the change in 5 minutes, and if it’s a FFlag, the server will recognize the change on a new server startup.

Adding a new FFlag

If you would like to add a new FFlag, you need to make sure you follow proper JSON structure. Let’s say I want to add a second FFlag in my JSON file called “test2”. The code will go from:

{
    "test": true
}

to:

{
    "test": true,
    "test2": false
}

Notice the comma? That is very important. Every new line needs a new comma. Then, if I were to implement the new FFlag into the DFFlag code, I would change the code to:

local HttpService = game:GetService("HttpService")

local function request()
	local response = HttpService:RequestAsync(
		{
			Url = "https://raw.githubusercontent.com/FxllenCode/TheInternFFlags/main/fflags.json",
			Method = "GET",		
			Headers = {

				["Cache-Control"] = "no-cache"

			}
		}
	)


	if response.Success then
		print("Status code:", response.StatusCode, response.StatusMessage) -- printing status code 
		local data = HttpService:JSONDecode(response.Body) -- parse the JSON into Lua
		if data.test == true then
			print("Test is True.")
			-- whatever else you want to do here
		elseif	data.test == false then
			print("Test is False.")
			-- whatever else you want to do here
		end
		if data.test2 == true then
			print("test 2 is true!")
		elseif data.test2 == false then
			print("test2 is false!")
		end
	else
		warn("The request failed:", response.StatusCode, response.StatusMessage) -- error handling
	end
end

while true do

	local success, message = pcall(request)
	if not success then
		warn("Http Request failed:", message)
	end

	wait(300)
end
Types of Data Supported

As far as I am concerned, only 2 types of data are supported in this system: Bool values, String values, and Integer values. Here is an example of all 3 types:

{
    "bool": true,
    "string": "poggers",
    "integer": 1337
}

I hope this tutorial could help you! If you have any questions or suggestions, please let me know! :grin:

Poll:

Was This Tutorial Helpful?
  • Yes.
  • No.

0 voters

shameless self promo

Follow my group for updates on the released of my upcoming horror game:

The Intern - Fan Group - Roblox

Thank you very much! <3

33 Likes

An interesting and helpful tutorial on implementing this. Perhaps an alternative for some people who aren’t familiar with Github would be a combination of DataStores and MessaingService? You can usually accomplish something like this with DataStores in less than 60 seconds. Thanks for making this!

I didn’t use datastores because I intentionally avoided services like DataStoreService when making this, as I was hoping for most of the system to be done via 3rd-party services in case something in your game is messed up and you cannot update the game.

This essentially is doing what could be done with MessagingService and DataStoreService but using a 3rd party to host it.

1 Like

Nice tutorial and concept.
This is usually what I do with my games but yours seems more like a remote toggleable settings page to control anything that needs to be dynamic in a game, this would be more useful in a scenario of pre-testing live updates in a game before the actual update, so you can diagnose any issues with an update and then ‘turn it off’! :grinning_face_with_smiling_eyes:

1 Like

I didn’t think of that! That’s such a good idea!

Interesting :thinking:

(I actually want to know how much you can decrease the time)


@FxllenCode How do I use this with GistHub? The problem is when ever the file updates the raw file link also changes, I’m not sure how to get one that doesn’t change

1 Like

That’s probably because your repository is public. I.E. GitHub pages for private repo’s costs money, might be the same on GistHub.

If you use a different hoster such as firebase, you could probably get it down to >30 seconds.

No it’s private, and the link keeps changing when I make changes I’m currently using a Github repository

Sorry I meant public! :sweat_smile: I need sleep…. The repository needs to be public for this to work unless you are a GitHub pro subscriber.

I bought the GitHub Pro just now but the link still changes

:upside_down_face:


I also tested with a public GistHub the URL will always change

You should set up GitHub pages now. It’s a different process if the repository is private. Feel free to send me a DM and I’ll walk you through setting pages up, it’s pretty simple.

Hey, I’ve made everything as you said, but it stills sending this to output: “Http Request failed: Can’t parse JSON”

Sounds like you are sending a POST request not a GET. Make sure you are using GetAsync. Also, are you using JSONDecode?

Don’t worry. It was just my error, I used “test” = true instead of “test”: true. Thank you anyways.

1 Like

You claim to say only two data types are supported but list 3. Was this a mistake?