2

I'm creating a system where there are config keys and values. So for example:

config.key = 10

Is an example of a configuration key and a value. These keys can also have overrides based on "dimensions". So for example, if we wanted to apply config.key to applications with the dimension foo, the overridden key would essentially be:

config.key.foo = 20

In future we may have multiple dimensions in arbitrary order, so this could be a possibility in future:

config.key.foo.bar = 30

A more concrete example would be if we had a key/toggle called display.pintrest.feed that has a boolean value. So the default value would be false, but you could have overrides like so:

display.pintrest.feed = false
display.pintrest.feed.femaleUser = true

Here femaleUser is a dimension (so we want to set the value of this config to true for only female users).

This is essentially what I am trying to do. My question is regarding persistence. What would be the best way to persist this kind of data? This is data that will be queried somewhat frequently but written to less often. The naive solution would be to use MySQL or PostgreSQL and create a table like this:

+----------------------------------+-------+
|                Key               | Value |
+----------------------------------+-------+
| config.key                       | 10    |
| config.key.foo                   | 20    |
| display.pintrest.feed            | true  |
| display.pintrest.feed.femaleUser | false |
+----------------------------------+-------+

But we lose the type safety of Value and also have a single point of failure. We also have a lot of redundancy (the base part of the configuration key is repeated each time). So I wondered about perhaps representing it as a graph so that I could write it to a graph database. I was thinking of modeling it like so:

enter image description here

Is this viable or overkill?

I don't mind using a simple key-value store either but it should be fault-tolerant and should be able to be clustered. Also we only really care about eventual consistency (i.e., don't mind it taking time to propagate changes to all the nodes).

So my question is what kind of data store should back this kind of data? Is a simple key-value store enough or should I go for a graph database? My rationale for the latter is simply to mitigate the redundancy from keys but I don't know if that's strong rationale.

1

You could use a slightly difference structure in your table, if you still wanted to go with a table-based solution:

key_values
----------
  id
  parent_id
  key
  value
  type_constraint_id

type_contraints
---------------
  id
  name

and then populate it like this:

key_values
----------
id  | parent_id | key       | value    | type_constraint_id
----+-----------+-----------+----------+-------------------
1   |           | config    |          |
2   | 1         | key       | 10       |
3   | 2         | foo       | 20       |
4   |           | display   |          |
5   | 3         | pinterest |          |
6   | 5         | feed      | true     |
7   | 6         | femaulUsr | false    |


type_constraints
----------------
id  |   name
----+-----------
1   | numeric
2   | boolean
3   | text

This schema allows you to store the hierarchy in such a way that you can query it directly, since it sounds like you're interested in in working with it in that way.

I've also added a type_constraint table and FK so that you can associate keys with named types. The database can't actually enforce these so you'd have to use this as a hint for your application to do type validation (or do it in the database with triggers). I'm not sure I'd bother if I was building this for myself, but you seem to want to have some sort of type-safety, this was the simplest way I could think to add it to this schema.

I suppose a graph database could work if these key/value structures get very complex, but I'm not familiar enough with them to know if they offer the type-safety you want and will work the way you need.

  • If there's one language being used by the client application(s), then your "type_constraints" table could hold the fully qualified type name of the variable type ("System.String", etc) so that reflection could be used to bind the database values to an instantiated Config object. – Graham Oct 31 '14 at 13:28
  • The usual way to handle this is to replace the value column with a set of typed columns (e.g., int_value, bool_value, string_value), and to use the correct column for the datatype. You could even go so far as to add a constraint (or possibly an insert trigger) to ensure that all but one of the xxx_value columns is NULL. – Ross Patterson Dec 30 '14 at 12:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.