Based on GraphQL
FDL is based off GraphQL, which makes the language concise and readable. Developers who have used GraphQL in the past will find that FDL's syntax is very familiar.
FDL supports all GraphQL types (except unions) and uses the same syntax for them. You can define objects using the
type keyword and enumerations using
enum. All primitive data types are supported. You can store complex data in Causal's data store. For example, you can easily store a list of results from a search engine or recommender algorithm in a Causal feature. This makes life easy for your data scientists as they work to improve the feature.
We don't support union types because downstream data warehouses typically don't support them either.
FDL, like GraphQL, supports two types of comments.
Internal comment lines are prefixed by
# and are ignored by the compiler.
External comments are strings added before the entity you are documenting. Multiline strings are surrounded by triple double quotes (
""") and single line strings are surrounded by simple double quotes (
Like GraphQL, FDL identifier names are case sensitive. However, unlike GraphQL, FDL uses these identifiers to generate code in case insensitive languages (like SQL).
In order to translate FDL identifiers into these languages without annoying workarounds like backquotes, the FDL compiler will automatically translate camelCase and PascalCase identifiers to snake_case in case insensitive languages. So, for example a feature named
SillyExample creates a table named
silly_example in the data warehouse.
However, if you also define a feature named
silly_example in your FDL file, both features would have the same table name in your warehouse, which of course won't work.
Therefore, the compiler gives you an error if you attempt to use 2 different FDL identifiers that would map to the same snake_case name.
For this reason, we recommend you use camelCase and PascalCase identifiers in your FDL files. This is typically the GraphQL convention anyway.
Input and Output Types
FDL doesn't distinguish between GraphQL input and output types. There is one object type, and you declare a new class of objects using the
type keyword. The
input keyword is unused.
Nullable inputs are treated as optional and will show up as
null in your data warehouse if not specified. There is no difference between not specifying an input argument and specifying null.
By design, FDL is more permissive about mismatches between the schema being used on the client (your front end), and the server. As you update the feature's data definition over time, this allows specific, well-defined behaviors:
- If the client calls the server asking for a feature the server doesn't know about, it will get the complete set of default values that are compiled into the client.
- If the client calls the server asking for a feature without a required argument, it will get the complete set of default values that are compiled into the client.
- If the client gets a response from the server that is missing a field the client is expecting, the client will return the default value for that field.
- If either the client or the server receive a field that they don't know about yet, they will assume it is because of a schema mismatch and drop the offending field.
This scheme closely mimics the schema migration approach used in the Avro wire protocol and has been tested in production many times.
If any of the above scenarios occur, Causal will register a recoverable error (so you know what happened), and will continue to return the appropriate data so your front end continues to function. In fact, if the front end cannot connect to a Causal server at all (e.g. if someone trips over the network cable), Causal will still return the default values so your site can keep running.