Spreading our tentacles taking a Django app global | Frederike Jaeger

This video features Frederike Jaeger at DjangoCon Europe 2021 in Online.

Spreading our tentacles taking a Django app global | Frederike Jaeger
0:50:32
Published July 14, 2021
2,758 views

Imagine you built a pretty snazzy Django app to transform your company's business. You're helping with revolutionizing the energy industry to make better use of green energy. Pretty cool right? Now imagine your company is expanding to new countries and not only that, other companies want to use your app too. Even better! But also imagine you wrote that app specifically with your company in one country in mind. This talk is going to cover the approach we've taken in transforming our app to work for multiple clients in multiple countries while still keeping the core of it the same.

Summary

Kraken, Octopus Energy’s Django-based customer management and billing platform, supports smart tariffs that shift energy use toward periods when renewable power is available, including times when customers may be paid to consume electricity. Frederike Jaeger explains how one large Django codebase serves nine installations across countries and clients, using continuous deployment, extensive tests, layered architecture, and plugins selected through Django configurations rather than scattered conditionals. She also describes a migration system built with Django REST Framework: client data is validated, staged, enriched with optional history, and converted into accounts without disrupting billing or customer-service records. The presentation ends while beginning to explain how configuration-specific test suites prevent changes for one territory or client from breaking others.

Key takeaways

  • Smart tariffs can move electricity demand away from peak periods and encourage customers to use surplus renewable energy.
  • Kraken is a very large Django application with more than 100,000 commits, over a million lines of Python, continuous deployment, and about 24,000 tests.
  • Customer migrations use Django REST Framework APIs for thorough validation, staging, account creation, and preservation of financial and historical data.
  • A common payload format allows accounts from multiple source systems to be migrated into Kraken at scale, including roughly 150,000 accounts per week.
  • Kraken separates common, territory-specific, and client-specific behavior through plugins, layered architecture, and Django configuration inheritance.
  • Abstract interfaces and configuration-selected implementations make missing integrations fail loudly instead of silently using unsuitable defaults.

Summarised automatically from the transcript.

Chapters

  1. 0:08 Introduction and Octopus Energy Frederike Jaeger introduces her background, Octopus Energy, and the Kraken customer-management platform.
  2. 2:28 The Energy Industry and Green Energy An overview of how energy moves from generation sources through the grid to consumers, and the challenges of using more renewable power.
  3. 5:33 Smart Meters and Dynamic Tariffs Smart meters enable time-based pricing, electric-vehicle tariffs, and incentives for shifting energy use.
  4. 11:06 Kraken as a Django Application The talk connects smart tariffs to Kraken’s large, rapidly deployed Django codebase and development practices.
  5. 14:11 Global Expansion Kraken expands from a single UK deployment to multiple countries, energy businesses, and licensed clients.
  6. 16:29 Customer Migrations The migration process moves customers from existing systems into new Kraken instances through organic growth or bulk imports.
  7. 18:52 Migration APIs and Validation Django REST Framework APIs validate, stage, transform, and create customer accounts while preserving financial and historical data.
  8. 27:24 Kraken’s Plugin Architecture A layered architecture separates core functionality from common, territory-specific, and client-specific plugins.
  9. 30:32 Django Configurations and Extensions Django configurations select apps, vendors, templates, and other implementations without scattering client-specific conditionals through the codebase.
  10. 38:15 Testing Multiple Kraken Instances The talk begins describing how shared, territory, and client-specific tests protect deployments across different configurations.

Transcript

9,425 words · auto-generated Show

Automatically transcribed, so expect mistakes in names and technical terms.

0:08

Speaker 1: Hi, I'm Fred Yeager and welcome to my talk, Spreading Our Tentacles, Taking A Jungle App Global. Now I realise this is a bit of a weird name, but I promise it'll make sense soon Now this is me. I'm a passionate rugby player, but perhaps a bit average in skill, but someone managed to get a bit good picture of me. So well done then. This is also me on the day when I graduated from my PhD in physics. So I did a PhD in computational physics where I've researched how you can use graphene membranes to help with water desalination. And then finally, this is developer me or lockdown at my parents developer me. So it's not my most professional setup, but that's what I had to make do with for much of the past year.

0:55

Speaker 1: So after I I left academia three years ago, I went into the into the software engineering world and I haven't really looked back since a little bit. And it's let me here. So I think I've I've done pretty well for myself So I work for the Octopus Energy Group. So the Octopus Energy Group is original from the UK, where we had a small energy supplier dealing in renewables. And since then it's grown a lot, not only the energy supplier, but the business as well. So we still have the the energy supplier for domestic use but also for for businesses. We've done quite a lot in the electric vehicle space. We have our own metering business. And then there's also Kraken Technologies, which is the tech branch of the Octopus Energy Group. We've also recently

1:41

Speaker 1: invested a lot in renewables. For example, you can here see our Pride and Joy, the number one fan. the first wind turbine that we purchased. We've also got something that we call the fan club, which is basically a com uh special deals for the community. living near the number one fan, which we've done because we care about the community, but also a little bit because the number one fan has to have a fan club. Now, I work for Kraken Technology. So as I said, that's kind of the tech branch of the Octopus Energy Group. And we have a product called Kraken. Now Kraken is a customer management and billing system that's used by energy suppliers. So we deal with anything from the integration with the with the energy industry. taking meter readings, doing the billing, taking payments,

2:28

Speaker 1: sending out comms, and also managing all customer contact between customer service operatives and the customer itself. This is just a screenshot of what it looks like or a fake account for the duck family, just so that you know what I'm what I'm talking about. So you can picture this when I talk about Kraken. Now as the Octopus Energy Group, our goal is to combat climate change. Now this seems like a pretty, pretty ambitious goal and you might wonder where does a billing platform for the energy industry come into this? But I'll I'll explain that. Um as David Affron said, we should stop all the damaging stuff and roll out the new green tech. So we want to be part of that new green tech. Now for those of you who don't know who David Attempurh is

3:14

Speaker 1: He is basically the voice of nature documentaries in the UK and he's a he's a big advocate for climate change. So we should listen to him. Now, how how does gre new green tech look like in this context of the billing system? In order to explain that, I need to first of all give you a bit of a 101 on the energy industry and how it works. Now on the left hand side you can see energy sources. So for example, you can see your solar energy, your wind energy, so the renewable sources, then the more traditional sources like coal or also nuclear. And all of these sources produce energy which then goes onto the grid. This might look a bit different between countries, but in general this is how it works. Now the grid takes the energy from the source and then distributes it to the consumers, which you can see on the right-hand

4:01

Speaker 1: side. Now something key to say which might not be obvious is that as a consumer you don't know where your energy came from. You just take take in the grid. It basically all gets mixed mixed up in the grid. Now there's another aspect here which I'm not going to talk about, which is where consumers can put energy back onto the grid, which might be, for example, if you have solar panels on your house and you don't use all the energy yourself or if you have an electric car that you can use as as battery, which releases energy onto the grid. And there's lots of really cool stuff in that space, but I'm not going to talk about it today. There's already so much to talk about Now, if we have the goal of making sure that more and more people use green energy and it becomes dominant as a source for energy, we need to tackle a few

4:48

Speaker 1: challenges that that arise from that. So one of them is that When the demand is high, we have to usually rely on the dirty or the more traditional energy. That's because it's just a more reliable source and there might not be enough green energy available at the time The other problem is that there might be too much green energy on the grid. Now that's a bit counterintuitive, but there can be such a thing as too much of a good thing. This is because when there's too much energy on the grid The grid is overloaded and it doesn't know how to handle all this energy. And what normally happens in that situation is that the wind turbine, for example, if it's really windy, it's going to get turned off. And not only is that really, really expensive, it costs millions of pounds. It's also obviously the opposite of what you want to do.

5:33

Speaker 1: You want to use the green energy when it's there. Now, our our way of tackling this is smart terrace. Now for smart terrace you need what's called a smart meter, and if you don't know what what that is I think they're not necessarily well known in all the countries. I'm gonna give you a very brief overview. Now if you have a traditional meter, what happens if you need to have a reading is either you look at it yourself, so you take a reading You go to your meter, you look it up, you tell your energy supply about your reading, or you have to have a meter reader come around who does the same thing for you. So for example, my parents, they have a meter reader come around once a year, uh, which means they get an accurate bill once a year, and the rest of the time they're they're just gonna build to estimates. Now smart meters can basically take the reading for you because they're smart.

6:18

Speaker 1: That means you never have to actually look at the meter and send a reading to your energy supplier. They can just get it directly from the from the meter. Another interesting thing is that they can get your readings at much more regular intervals. So for example, smart meters in the UK get readings every 30 minutes. In Australia they can get readings every five minutes. So that's really, really granular. And this means that not only you know your usage, so you can actually see, oh, I'm using a lot of energy normally in the morning or in the evening after work. But also we can use that to charge you different amounts at different times depending on how how much the energy should be worth. And this this is what we're we're doing quite a lot and where we're hoping to address those challenges that I mentioned previously So at Octopus Energy, we have two smart tariffs

7:05

Speaker 1: or two groups of smart tariffs. One of them is called Octopus Energy Go, and this is one that's aimed at drivers of electric cars. So here you have a period of four hours over overnight where uh energy is really cheap. This means that you can just use that time to charge your electric car And it means it's a lot cheaper for you to have an electric car and then you don't do it during peak hours. So you don't do it after work, you do it overnight. And it's cheap and it's it's It's a a great deal if you have an electric car. The other one, and this is a really cool one, is um the agile tariff. So the agile tariff has different rates every half hour. Every half hour because it's in the UK where smart meters uh give us readings every every 30 minutes. And these rates track the whole say prices. So that means when it's cheap for us as a supplier to buy energy

7:54

Speaker 1: uh we'll make it cheap for you to use and if it's expensive we'll make it more expensive for you to use. So if you look at the graph there you can see that there's the nice peak um peak after after work. When people come up from work, that's always when energy is expensive, which is why it's expensive for agile users to use. But the rest of the time it can be cheaper Now, the cool thing is that it not only is cheaper at at certain times of the day, but it could also be that you're being paid to use energy at certain times of the day. So these are what we call plunge pricing events And this is when we have that scenario that I described earlier where there's a lot of energy on the grid and we need people to use it. And that's when we're paying the customer to use the energy because we want to get it off it. And we're giving customers this financial incentives to actually

8:42

Speaker 1: use all that energy that's there that's otherwise not being used. I have an example here of a of a bill for a customer for a single day where this kind of thing happened. So this would have been where maybe there was a lot of wind. I doubt there was a lot of sunshine because this is from December. So it's probably wind. And you can see here on this bill the different rates. So I'm just going to highlight here the rates which are negative and negative means that we paid the customer to use energy in that period. So here's a two-hour period overnight where we paid the customer. And then there's also actually quite low rates before that. So also not a bad idea. Now if you look at the customer's usage at the top in that graph. You can see those those dark bars and that's the customer's usage where the pink lines are the rates.

9:30

Speaker 1: And then you can see that this customer has really switched their usage to that time period because they knew it was they were being paid to use energy then. So there's obviously some other usage throughout the day, but a lot of it was moved to that period. And then if you look at the total cost for that customer for that day, it's actually negative. So the customer was paid to use energy that day. So this is really a win-win because the customer gets a great deal. They get paid to use energy. Who can say that? And also we're we're helping getting the energy off the grid when it needs to be taken off. Another cool thing you can do with with tariffs like that is that we're making uh the the usage and the rates available uh to the customer via an API. And some of our customers have built apps for this where you can track the rates and

10:15

Speaker 1: you can you can see graphs They've built other tools where you can uh set devices to use energy at a certain time when the rates are below a certain level and really interesting things like that. And we have a really vibrant online community of people using this this TEV, which is which is really quite new. And there's so much engagement there. And people are really interested in this, which is really nice to see. Now, if we're coming back to those challenges that I described earlier, so one of them being that when the demand is high, we're having to use the more traditional energy sources and the other one being that there could be too much green energy on the grid, we've actually addressed both of them with smart tariffs like this. So one thing is that we're encouraging people to switch their usage away from peak hours so that they can actually use energy during times when there is green energy on the grid.

11:06

Speaker 1: rather than just um having to use the the more reliable dirty energy. The other thing is that we're we're we're paying customers to use energy when there's too much energy on the grid. And this has actually worked. We've we've had feedback from from um the industry in the UK that actually our customers have really helped up with this problem. So we've addressed both of these, which is pretty cool. And this is where we get to in tech because tariffs like this don't just happen. So with with the more um out-of-the-box energy uh software that's out there. You can't just easily implement a tariff like that. It takes more work and obviously with bigger companies, this will always take time because traditionally uh bigger companies iterate very slowly.

11:52

Speaker 1: Whereas we're people we we move fast. We we like building new features and something like this where we really see a value in it, we build it very quickly. So for example, Agile we built in a few weeks. So all of all of our custom interaction, including the billing, so including the bit that handles the tariffs and everything else around it, as I explained, is all within Kraken. And Kraken is just one big Django app, basically. So we use Django for that view that I showed you, that customer page that's built using Django views and templates for some of our APIs. for the database storage and it acting with the database for everything really. As it's just one big app, it actually all lives in one big repository.

12:38

Speaker 1: And when I say big, I do mean big. So we have over a hundred thousand commits. We had the anniversary just last week. We've got about 30,000 merged pull requests and more than a million lines of code. And that's just Python code. So I'm sure there's a lot more. I only counted Python code for this purpose. We do continuous deployment. So that means that we deploy a new version of Kraken several times a day. So every time a pull request is merged, a new version of Kraken goes out. And at the moment we merge maybe 50 pull requests a day, but the numbers are are steadily going up. Obviously to make sure that we're not breaking anything, we have to run a lot of tests. So for example, we have 24,000 Python tests that we run every time a pull request is merged,

13:25

Speaker 1: just to give us that that bit of security to make sure that we're not breaking anything if we change something so regularly. We also have a lot of linting. So the day we introduced Black was probably my favorite day because now everything is nice and neat and everything looks the same and there's clear standards of what to use. We also have FLEC 8 for some additional Python linting. We started using typing a lot once the code base got bigger and used MIPI for that. And we also have a lot of conventions, so you can look up some of our conventions online as well. We have lots of rules about things, but if you're working on a really big project like a big Django app like this, you need to have rules. Now the last year, last year and a bit now, um have been pretty big for the Octopus

14:11

Speaker 1: Energy Group. Um not only have we expanded as an energy supplier, so we've we've entered the market in in different countries like Germany, the US, uh, Japan, and New Zealand. Uh, we've also licensed Kraken our platform to existing energy suppliers. So uh two in the UK including Eon, who are a very big supplier, and also Origin. in the Australia. And with that came uh quite a bit of investment so that we've actually reached double unicorn status after less than five years of of even existing, which is pretty neat. So we went from in 2016 when we started having one single Kraken instance just in the UK for the UK NG supplier to now having nine. running in different countries, both for our own energy

14:57

Speaker 1: supply businesses, but also for our clients who license Kraken as a platform to use for their own business. Now just to show you how far we've we've gone really in the world, these are the the places where we're starting completely from scratch, either as our own business or supporting another business with zero customers and then building building up the customer base from Kraken from the start. And then these are the places where we have an existing customer base and we're moving them onto Kraken to continue to grow the business. And obviously then there's the money aspect which will help us actually do that because you do need support, you need more developers, the more countries you've reached, the more developers you need to support that. Now, obviously

15:43

Speaker 1: our reaction to this was was a bit like that. It's pretty neat to see people believe in our mission and believe in our product. uh and being able to to do more with it because the more investment you have, the more you can do and the the more you can actually realize your vision of it But not gonna lie, there was a little bit of this because it's pretty daunting. It's it's a big deal. So if I go back to what Kraken covers I've just shown you how many different countries we've expanded to and the different new clients that we've got out of these things. uh most of them are specific to either the country that you operate in or the client itself. So the the industry is obviously different in different countries, the communications might go out differently. um the the payment systems are different, the taxes are different.

16:29

Speaker 1: So there's so many things that are different either depending on your client or depending on on the territory or the country where you operate. So there's a lot of challenges in that So I'm going to talk you through how we're supporting that and how we're doing it. First by talking about how we're getting customers onto the platform. Then this is the main bit, how we're making Kraken work for all these different places while still keeping it in one single Django app and then also how we're supporting our clients in in improving their their customer experience. Now every time we set up a new kraken we start out with what we call a baby kraken, which just has the basics in it. So it has a few things that you need for, for example, um the the permissions and and roles for customer service uh operatives and things like that.

17:18

Speaker 1: But It's basically brand new. And then there's two ways of getting customers on it. One of them is organic growth. So when you just acquire new customers um organically or the other one is customer migrations where you merge them over from uh from an existing system. Organic growth is obviously quite a slow process. You'll you'll start up with a friendly account and then you slowly add more, but you have a lot of time to um to kind of make sure everything works because you don't have very many customers to start with. With customer migrations it's a bit different because You start up with a few test accounts to make sure that your migration works, but then you can actually just match uh migrate them over very quickly because There's nothing stopping you from it. If it works, it works. And we're actually doing that in several places around the world at the moment

18:05

Speaker 1: and quite quickly. So it really is quite a quick process. But it does present some challenges. Now obviously the direct sign-up route is important, but the custom migrations one is a bit more interesting from a technical point of view, so I'm going to talk about that a little bit. Now um we have a quote here from the CEO of of ENUK talking about the migration that we've recently done with them in the UK. And it's Actually uh really interesting to see how many people from the industry uh actually saying um how fast we're doing it. So I'm I personally work on migrations and I never really realized how big a deal it was until I spoke to some people from the industry.

18:52

Speaker 1: Because for us it was always um pretty easy and I don't mean that in a braggy way. It's just we just did our job and it seemed to work fine. But apparently it's it's pretty well received, which is which is always nice to hear. So for our migration approach, we uh use a Django REST framework to create some APIs to facilitate migrations And I'm going to talk a bit about what kind of APIs we use and what the general process is also for extending these. Now the general idea is that we take some JSON data and then we turn that into an account and crack it. The important thing here is that you need to make sure that an account can live on and Kraken as it had before. So the customer shouldn't really notice that they switched to a different system. Obviously the important bits are the financial aspects, so you need to make sure you don't double bill a customer or double charge a customer and things like that.

19:44

Speaker 1: But you also want to have enough history there so that when this customer calls with a problem and the customer service operative can just respond and has all the information that they need. So these are kind of the key things that you you have to make sure you do right when you do a migration As I said, we use some APIs to facilitate that. I'm going to explain a little bit what they all do and the process that we have in place. So first of all we have a validation API. And this is an API that we make available to our clients to send the data to and just to validate if it's valid or not. And we don't we don't really uh care how many errors they get. They can just use it as much as they want, send the data there, and they can use it for their data cleansing

20:31

Speaker 1: or make sure that they have the right customer groups and our validation is very thorough. So if if an account passes validation in this API, it should be good to go. The next stage is where we're saving that data, that validated data, to a staging table Now one of the reasons why we have this staging table, this kind of intermediate stage, is because A, it gives you the opportunity to update the data before actually creating an account. if you had another payment come in that you want to make sure comes comes across into kraken, for example. But it also means that we can track track the migration better. So not only can we track how many accounts we've created, there's also sometimes some post-migration actions that might have to happen and we can track those on that that model as well.

21:19

Speaker 1: So we have that kind of staging area. And then finally we create an account from that data that we have in the staging area. And that should be a pretty smooth process because we've done all that validation. And then it should just be a single step to actually create that account. Now just to give you an idea of what that data looks like, it often corresponds quite closely to the models that we have in our database. So for example, you'd have the billing name field on the model, so you're also asking for it in the migration data. But sometimes there is a bit of transformation that has to happen. So for example, we'll collect some data in pounds. but we save it in

22:04

Speaker 1: database and pens. So it's not a direct one-to-one mapping. With foreign keys, we just convert them into lists basically. So if you if you have a foreign key between the user and the account, you then have a list of users that you have in the import data. So That bit is is pretty simple on the whole. Validation, as I said, is a key element of it. And there's there's several aspects to it. You have to make sure that the data is actually valid from the Data-based point of view, so does it conform to the models? And also is it is it valid from a business logic point of view So we we use standard rest framework serializers for this, but we don't really use model serializers. And that's partly because As I said, sometimes it doesn't correspond exactly.

22:49

Speaker 1: For example, the pens and pounce issue. Sometimes we want to set some kind of default value. And sometimes you can just not represent um how we save it in the database um in the same way in the in the migration data. So some things particular to do with transactions and the financial side of it. There's just no one-to-one mapping. But we do try to make sure that, for example, the max length of a of a char field is obeyed in the same way and things like that Our main validation actually comes in custom validate methods that we write. So that's where normally all the business logic lives. So important things like again the financial side If we get some transactions in, we need to make sure that the the balances

23:34

Speaker 1: all made uh match up. Things like that. That um Just we have all the information that we need for the account to live on and Kraken. And that's where where this validation comes in. Like do we have all the right dates or do we have all the right readings and things like that? And there's some pretty complex validation validation methods in there, but that's what we really need to make sure the account goes on and to make sure that we don't have any problems when we are actually going to create the account. Now something something nice is that um as a client we kind of we have the the base required fields that we need to make an account live on and kraken. So that's the the main thing. This is everything you need.

24:20

Speaker 1: Then the account will live on and Kraken, we'll have all the right balances, and it'll go smoothly. But you can also add on lots of optional things to make make the account richer. Uh so have a richer history. So add notes, for example, appropriate statements, debt history , it could just be um the payment history. There's no requirement to migrate it, but you can and it'll help. your customer service operators looking at it, um, looking at the account, they'll they'll have a much clearer picture of what the account looks like and can answer queries better. But it's not required. We do make sure everything that you need is there, but other things you can just add on. In the same along the same line, we can just add new features in. So we we have the basis, we know what we need, but if

25:06

Speaker 1: as a client you need more, if a client comes to us and says, actually we'd quite like to have this information in Kraken as well. because it's something that that we want to see on an account, it's pretty easy for us to add it. So as you saw we use our serializers, you just add new items to the serializers and obviously to the docs. And then we just need to add a function to a use case to actually add that bit of data and save it in the database and out comes the account with a new feature. So we do that quite regularly and and the migration API has grown a lot to have more and more features and collect more data, but as I said, a lot of it is optional because you don't have to have it the account doesn't need it. But it's always nice to to add more features on and we can be quite flexible on it because we we iterate quickly

25:52

Speaker 1: and we do do that continuous deployment um and that's our ethos so we we we update it quite regularly. Um another nice thing is and I think this is a big part of why why it goes so smoothly is that we have that signal-defined payload that we've decided on. And this means that once the accounts get into Kraken, so once we have the payload, it's all the same. It doesn't matter what source system it comes from. And even on the source side, you just have to do the mapping once. You have to understand what each field represents once. And once you've worked that out, you can generate the payload for every account So this means we can do migrations from different source systems into the same instance of Kraken all at the same time without any problems.

26:39

Speaker 1: So we're currently doing a migration from six or seven systems into Kraken. So it's pretty neat. But it just means that that it's a really smooth process, our end, and we we don't need to um worry about differences between source systems. So this just to give you an idea of numbers, the kind of large numbers that we're migrating is about 150,000 accounts. a week. So that's a that's a pretty big number. And once you have it set up, like I said, it just runs and does its thing, which is which is really nice. Now I'm going to get to the bit of talking about how we customize Kraken. So I talked about how we can get client accounts into into

27:24

Speaker 1: Kraken, but as I said, there's a lot of uh things to consider when you have different versions of Kraken, but it all lives in the same Django app. The way we think about these is with the concept of plugins. So you have the core Kraken, so you have the core Kraken code, and then you have all these other bits that might be different that plug into the main code. In order to explain where they fit in and how we do that in practice, I need to talk about the core a little bit and about how that's organized and structured. So this is the the kind of layers that we have in our code base. And the idea is that the lower layer doesn't know about the upper layer. So the lower layer never calls the upper layer.

28:09

Speaker 1: Instead you always call down. So you have your interface layer where which is basically entry point into Kraken. So this will be from the support site or be a customer query. And this is where our views live, our APIs live, and our management commands live. Then you have the application layer, which is also sometimes called the service layer, I think. And that's where your use cases live. So this these are your kind of your key unique actions that Kraken has to perform But for the actual implementation of that, it goes to the domain layer. So this is where our database operations and our queries live and all the business logic lives around deciding how to implement this action. And finally, the data layer just has our jungle

28:56

Speaker 1: models, and we keep our models quite lean normally So a lot of the things that for some people live on the models for us lives in the in the domain code. So where do these these additional bits come in? Where do these plugins come in and how do they fit into this whole architecture? The plugins kind of sit outside of this but feed into the domain. So within our plugins, we again have some categories. So we have the common category. So that would be for things like let's say a payment vendor, which operates in different countries. So it can be common across different territories, but it's not something that we want core kraken

29:43

Speaker 1: to know about. As I said before with those layers, the idea is that um a single layer doesn't really know about the exact details of the layer above. So we don't want the domain layer to know about the implementations in the plugin. So if you have a payment vendor, even though it's common Kraken doesn't need to know about how exactly it takes a payment. Kraken just wants to say take a payment from a payment vendor without knowing the detailed implementation. So that's why it would live in the plugin layer. Then you have the territory layer where you would you'd have, for example, the industry information and interaction with the industry. So that, as you can imagine, is always going to be different per territory because the the industry is just organized in a completely different way. And then finally you have the client layer and that's where all the client-specific differences

30:32

Speaker 1: live. But just to reiterate, the domain layer should not know about the details of the plugin layer. I'm going to talk a bit about how we actually do that from a coding perspective because it's it's really quite interesting Just to set the scene a little bit, let's say we have we're operating on two different territories, one is Antarctica and one is Monaco. So you can imagine they are quite different. And then in Antarctica we have one client and in Monaco we have two clients. So this this is a pretty um common common picture that you have several clients in the same territory and different territories. So we use Django configurations a lot. And we use that to define our settings for all the different

31:19

Speaker 1: Kraken instances that we have. So as always, as you also have in the plugin layers, we start with something that's common. So we have our base configuration. And in the space configurations, we'll put all the settings that are common between all the different Kraken instances, but we also define all the other settings. Because this basically helps if you have a new Kraken instance, you can just go to the base and you know which settings you need to add So it gives you a nice view of what you do need to add and it has all the common ones. Then you have the territory settings So there's territory configuration and that inherits from the base configuration. So you don't need to redefine everything that's common in the base. Where you can overwrite any settings with anything that's common for the whole territory.

32:05

Speaker 1: And then finally you have the client and that's where all the client-specific configuration lives. And this could, for example, be a setting that defines the URL for links and things like that. So these are very specific to a client. Where this actually comes in in terms of the different Kraken instances is that we deploy each Django app with different configurations. And they all have their own DB. So we we have one common code base and the common Django app, but when it's deployed, they're deployed with different settings, which are defined from their configurations, and they all have their own database. One example where we can use this is installed apps. So we can always obviously have a common set of installed apps that we want to have

32:52

Speaker 1: But there might be other apps that we need to add, for example, to do with the industry settings that might be different. And we don't want to install unnecessary apps for different Kraken installations. And this is how we use configurations to manage that. So if you can look at the installed apps property, you can see that we have a list of apps and these are common to all in the base class, but then we also have another setting. uh the feature app setting that we've defined as an empty list for now, which can extend this if you want to, but you don't need to. Doing it like this and organizing it like this means that if you want to add an app in another configuration, be it a territory configuration or client configuration. All you need to do is override the feature apps setting.

33:38

Speaker 1: So that makes it really easy because it's just one line and it's super easy to update it But the real important thing is how we handle application code. So this is where all those layers come in that I showed you earlier. One thing that we really, really want to avoid with using Django configurations is something like this, where you have lots of if statements all over the code base saying like if it's this brand or if it's this client, then do this. And what often tends to happen is that you have some kind of default that you fall back on because you didn't want something to break. And that default might be completely inappropriate. So if you get a new client, what you have to do is you have to find all these if statements and add a new one. And if you forget, you might fall back to

34:25

Speaker 1: to a default which is is not right for for this client. So that's um really inefficient. It's not very nice to to read and it's also very prone prone to error. So this is where we want to use configuration to make it make it much nicer. The way we do that, I'm going to explain now. As I said before, if you have your domain layer, you don't want that to know about a specific implementation. So here I'm using the example of a print vendor. So print vendor would be the people that we send PDFs to to print and then send to a customer as letters. If we want to use the print vendor in the domain We have to know what to expect from a printbender, but we don't want to know the exact implementation of the printbender.

35:10

Speaker 1: So we define a class here where we have uh attributes and methods but they're not assigned any values or they raise a not implemented error. What's useful about that is that if you implement a a new print vendor for a specific client, for example, and you've forgotten to implement a method, it'll fail loudly. And we want things to fail loudly so that we, as I said, we don't fall back to any inappropriate defaults You can then have the different print vendors in the plugins layer, which which use the domain layer base print vendor as as a base. So here you can see that we're in the plugins folder and in this case in the territories folder. and we've defined the Antarctica print

35:56

Speaker 1: igloo, the print banner for Antarctica, and we've overwritten all the things we need to overwrite. Similarly, you can have that for different lines. So it might not be the same one in a territory. So for Formula 1ogy. we have the faster printing vendor and for for YachtPow we have the C your print vendor, but they all inherit from the domain one. And that means that we we define all the the methods that are already defined on the on the base one. and we just override them. That means that the domain can use these print vendors because it knows what to expect. Now how do we get from From those print vendors in the plugin to the domain, how would we tell the domain to use them? This is where Django configurations come in again. So if you look at the configuration for Formula 1

36:41

Speaker 1: and G, for example, If we add a print vendor here, a print vendor setting, we just add the code path to the to the actual class in the plugins layer. And then in the domain layer, we'll just have a function which grabs the print vendor from settings. So we just import it straight from the setting. And then when we want to use it, we can just get the printbender and use it right in the code. as you can see here. And that means that the domain never actually explicitly calls plugins. It doesn't need to have any kind of if statements Because otherwise it would probably look a bit like this. And this is almost a nice version of it. It could look a lot worse like the example I showed earlier. So this is a really neat way where we're using configurations to then in the code base

37:28

Speaker 1: decide which which um which print vendor to use from the plugins. Another example is emails because as you can imagine those would be quite different between different clients. Here once again in the domain, we don't want to know about any specific client implementation. So we just have a function that says use this template. But then we can have different templates for different territories or for different clients. And we do that by just pointing to different template directories in the settings. And it's not just the templates themselves, we can also define the styling in the settings as well. So you could say use the same template, but use different styling.

38:15

Speaker 1: And that all doesn't need to live in the domain and it shouldn't live in the domain. So the domain function is nice and clean and it just does its job and doesn't know about any of the other changes. Now, as I said before, we redeploy Kraken many, many times a day. And then I showed you how we deploy Kraken to different instances using the different configurations. To make sure that we don't accidentally break something for one of the clients, we have to have a lot of tests. And here again, we're using configurations to make sure everything runs as expected and works as expected. So this is just a sample split of our test folders. So we have the common folder and this is where all the tests should live for anything that's shared between all the different Kraken instances. And then you have the territory folder

39:03

Speaker 1: where you have the tests that only apply to certain territories, and then you have your client folders, which contain the tests that are very specific to a certain client. We use PyTests and the nice thing is that you can if you're using Django configurations, that works really nicely with PyTests. So here you can just pass in the configuration name using that DC, so the jungle configuration flag, and then you have your folder test path. So for example, for ISIS Energy, you'd want to run the common tests with that configuration and the Antarctica tests and also the ISIS energy tests, of course. This is how we build up our test suite. We run all the appropriate tests with all the appropriate configurations. And if it changes, you make someone break something for one configuration, then we'll know.

39:50

Speaker 1: And we won't deploy, obviously. So I hope I've shown you how we use Django configurations to deploy Kraken with different settings, and then we use the settings to control the plugins or pick the right plugins and control features and how we also use that to make sure that we don't accidentally break anything and we have really wide test coverage. The final bit that I just want to talk a little bit about is how we can support clients because we we run Kraken and Kraken has does have this this web app which is used by the customer service operatives, but we don't control the clients' personal online accounts for for each customer, for example, but we can support them. So we use GraphQL for that. We make GraphQL

40:35

Speaker 1: queries available to the clients so that they can use that for their online account. And one of the reasons we use GraphQL because it's super flexible. So for those of you who don't know GraphQL, the QL stands for query language, and it was basically designed to do something like this. So to return a lot of information. in a single query. There's a single endpoint. You make a query, you tell it exactly what information you want to get back and you will get exactly that and all in a single single query. Something that's a bit different from other APIs is that you don't have explicit error handling. So if there's a problem, you can see it from the response, but not from the response code For example. So in GraphQL you have the concept of queries, which is basically the read operation. So that's just returning data.

41:21

Speaker 1: And that is, as I said, what it was designed to do. And then you have mutations which you can use to do the create, update, or delete operations. So that's just for making any changes to the database and interacting with the database on our end. Just to give you a quick overview of what this looks like. I mean this is not a GraphQL tutorial, but this is just a quick view of it You have a single endpoint, as I said, and then in your payload you'd have variables, which is basically your query variable. And then in the query you have the actual GraphQL query which looks a little bit like this And here you can see the account and then the account number and the billing name. And in this case, because it's a query, the account number and the billing name is what we want to have returned.

42:09

Speaker 1: But I could have just said, I just want the account number, and then we would have only returned the account number. Now we need to obviously define on our end what we want to make available in a query like this. And that's where return types come in. And this is where we have another neat integration with Django. So you have your query and then you want to decide what you want to make available uh for the caller. And you define that inner type. But with with some with a package called Graphene Django. So Graphene is the normal Python integration with Jang uh with GraphQL. Graphing Django as the Django specific integration, you can define something called a Django object type. And what you can do here is that you just say which model you want to use and which fields you want to use

42:56

Speaker 1: And that makes it a lot easier rather than defining the whole type from from scratch, just to compare. At the bottom here you can see what it would look like if you had to define the type from scratch. So you'd have to give it you'd have to give it the type. So you'd have to say is it a string. as a number, that kind of thing, and you'd also have to uh tell it where to get it from from this object. So the object here is the account, but you need to tell it where to get it from on the account. So using the Jungle object type, you can imagine is a lot neater. And especially what I said before, with the idea being that you use a single query to get back all the information you need. you want to be able to turn a to return a lot of information. So you don't want to have to write this for every single field on a model

43:43

Speaker 1: You can use the Jenga object types to make it a lot easier to return all the information and it can save you quite a lot of work Now the way we use this is by giving our clients the option to use queries to kind of populate the online accounts, so that's where they can get all the data from from Kraken and and show it on their online account however they wish. And then they can use mutations to make changes. So for example, to make a payment or to update their payment details. or to change a tariff. So we make mutations available for that purpose. So we can do both directions. Another nice thing that we do is that we have this project that we call Blueprint And this is where we basically have a sample online account that we can give to clients to use and that uses all those GraphQL

44:31

Speaker 1: queries and mutations that we have available. And they can either just take that and customize it a little bit and use that for for that purpose. Or they can just see it as an example of how do you use this query or how can we make use of all this data that we have available and how can we show it in the most effective way So I think that's really helpful for someone who's choosing to license our system , that they can build build their online account from that really easily. So I hope I've given you a bit of an overview of how we're using Django in all the different contexts. So for customer migrations where we're using the REST framework to build our APIs. and migrate large numbers of customers onto Kraken. And also then how we're using

45:17

Speaker 1: jungle configurations, and this is really a key part, how we're using jungle configurations to customize Kraken while still having everything in one app. And then finally how you can use um Django integrations in in with GraphQL to make queries really, really easy to build. So I hope that's been helpful. So where has all this taken us? I spoke at the start about how we went from having a single Kraken instance to then having nine of them. And this is reflected in the number of households that are on to Kraken at the moment. So we obviously started from from very little and then you could just see the growth of the octopus energy supplier But now it's actually gone up pretty rapidly because we've now licensed it to so many um

46:04

Speaker 1: so many other clients and because we're expanding so much. And this is just the stage that we're at right now. So we actually contracted to do another nine million I think and and we are constantly growing. So it's it's going up and this there's going to be more challenges, obviously, um outside of the ones that I've just addressed. But I think we've got a pretty good good handle on it Going back to the smart tariffs, um explained above, um we currently for Octopus Energy UK have about five percent of our customers with smart meters on smart tariffs. Now that might not sound like a lot, but actually given that they're so new, it's it's a pretty big number and the numbers are growing every day. And for example, one of our clients in in the UK, Good Energy, they've just launched their own smart tariff.

46:50

Speaker 1: So you can see that that they can really make use of of our technology and our way of working and our really nice integrations with Django to to make this happen. So I hope I've shown you that Django and Kraken make a pretty good team. That having Kraken as a Django app really makes our lives so much easier because there are so many integrations out there. And it's it's really nice to manage everything in one place and in one system. And I think I um I I hope I illustrated that and gave you a good overview of that. And finally, these are all the places where we're currently hiring. So if this sounds good to anyone, and if you'd like to work on a really big Django app like that with all these interesting challenges that we've got

47:37

Speaker 1: then please do uh please do apply. We'd love to have you. Thank you very much. Yes, okay. If anyone's got any questions, feel free to ask. I think there's still people joining, so we can also wait another minute or two.

48:00

Speaker 2: Can I ask you a question? Can you hear me? You can hear me? Okay, okay, that's great. Thanks for the presentation. It's always good to see

48:08

Speaker 3: Let's say Django used in such a large scale on and

48:12

Speaker 2: such global and all these challenges has to do with the culture and languages

48:17

Speaker 3: and things that are uh put have to be put inside all these different customers. Um I was wondering um

48:23

Speaker 2: in terms of of security

48:26

Speaker 3: I think you also have to uh adhere a lot to kind of uh local uh

48:31

Speaker 2: Yeah, r rules like GDPR, things like that. How do you manage um

48:37

Speaker 3: uh maybe not GDPR?

48:38

Speaker 2: I I understand that, but uh let's say uh

48:40

Speaker 3: security, do you have uh penetration testing

48:44

Speaker 2: things in place? Do you have regular visits or audits uh by customers, things like that.

48:50

Speaker 1: Um so this is not my area of expertise, but yeah we do have some um penetration testing from time to time. I don't know how often or how regularly. It's sometimes driven by our clients as well. And they we have our own security audits and they sometimes do their own security audits. So there's a few things going around. So I d I don't know the details herself, but um yeah, it's definitely it's definitely half thing Anyone else with a question?

49:22

Speaker 4: Thanks a lot for this great talk. I was really impressed to see how you uh did it. And I think that um uh we can learn a lot here. I'm working for a small startup, so we are not in this we did not reach this uh um um yeah status so far, but I think We can learn and that's yeah. Thank you.

49:49

Speaker 1: I mean we had to learn the hard way as well, right? I mean obviously you always try and design everything as best as possible, but um There's always new things that come up and you have to think of new ways of handling it. Um but I think hopefully we've done it reasonably well Otherwise, I'm also just available on Slack as well. If anyone wants to ask, I'm there, I'll be checking back regularly. So if no one else has any more questions, I guess we can leave this probably. Shout now if you want to ask a question. Otherwise, yeah, just hit me up on Slack and I can uh I can respond there. Cool

Questions this talk answers

What is Kraken, and what does it do for energy suppliers?

Kraken is a Django-based customer management and billing platform for energy suppliers. It handles industry integrations, meter readings, billing, payments, communications, and customer-service interactions.

Discussed at 1:41

How do smart energy tariffs help balance the electricity grid?

They encourage customers to shift usage away from peak-demand periods and toward times when renewable energy is plentiful. During periods of excess generation, customers can even be paid to use energy, helping prevent renewable power from being wasted.

Discussed at 5:33

How large is the Kraken Django app, and how is it deployed?

Kraken has more than 100,000 commits, around 30,000 merged pull requests, over a million lines of Python, and about 24,000 tests. It uses continuous deployment, with a new version released whenever a pull request is merged—roughly 50 times a day at the time of the talk.

Discussed at 12:38

How do you migrate existing energy customers into Kraken?

Kraken uses Django REST Framework APIs to validate incoming JSON, save the validated data in staging, and then create accounts from it. The process preserves balances, billing history, readings, and other information so customers can continue without noticing the system change.

Discussed at 18:52

How can one Django app support different countries and clients?

Kraken uses a plugin architecture layered around a shared core: common, territory-specific, and client-specific code plug into the domain layer. Django configurations select the appropriate settings, applications, vendors, templates, and other implementations for each deployed instance, while each instance has its own database.

Discussed at 27:24

How do you avoid filling a multi-client Django codebase with if statements?

The domain layer defines interfaces or base classes for things such as print vendors, while country- or client-specific plugins implement them. Configuration points to the correct implementation, so the domain code stays unaware of particular clients and missing implementations fail loudly instead of silently using an unsuitable default.

Discussed at 33:38

Note: We understand that names change, people change, and bodies change. We respect each individual's journey and privacy. If you have any concerns about a video or need us to remove content, please don't hesitate to contact us. We will handle your request with care and promptly address any issues.

More videos from DjangoCon Europe